mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
回退
This commit is contained in:
@@ -26,8 +26,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key SLAB_BLOCK = Key.from("craftengine:slab_block");
|
||||
public static final Key STAIRS_BLOCK = Key.from("craftengine:stairs_block");
|
||||
public static final Key PRESSURE_PLATE_BLOCK = Key.from("craftengine:pressure_plate_block");
|
||||
public static final Key PICKAXE_BLOCK = Key.from("craftengine:pickaxe_block");
|
||||
public static final Key PLACE_BLOCK = Key.from("craftengine:place_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -52,7 +50,5 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(SLAB_BLOCK, SlabBlockBehavior.FACTORY);
|
||||
register(STAIRS_BLOCK, StairsBlockBehavior.FACTORY);
|
||||
register(PRESSURE_PLATE_BLOCK, PressurePlateBlockBehavior.FACTORY);
|
||||
register(PICKAXE_BLOCK, PickaxeBlockBehavior.FACTORY);
|
||||
register(PLACE_BLOCK, PlaceBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public abstract class FacingTriggerableBlockBehavior extends BukkitBlockBehavior {
|
||||
protected static final List<Key> DEFAULT_BLACKLIST_BLOCKS = List.of(
|
||||
Key.of("minecraft:bedrock"),
|
||||
Key.of("minecraft:end_portal_frame"),
|
||||
Key.of("minecraft:end_portal"),
|
||||
Key.of("minecraft:nether_portal"),
|
||||
Key.of("minecraft:barrier"),
|
||||
Key.of("minecraft:command_block"),
|
||||
Key.of("minecraft:chain_command_block"),
|
||||
Key.of("minecraft:repeating_command_block"),
|
||||
Key.of("minecraft:structure_block"),
|
||||
Key.of("minecraft:end_gateway"),
|
||||
Key.of("minecraft:jigsaw"),
|
||||
Key.of("minecraft:structure_void"),
|
||||
Key.of("minecraft:test_instance_block"),
|
||||
Key.of("minecraft:moving_piston"),
|
||||
Key.of("minecraft:test_block"),
|
||||
Key.of("minecraft:light")
|
||||
);
|
||||
protected final Property<Direction> facingProperty;
|
||||
protected final Property<Boolean> triggeredProperty;
|
||||
protected final List<Key> blocks;
|
||||
protected final boolean whitelistMode;
|
||||
|
||||
public FacingTriggerableBlockBehavior(CustomBlock customBlock, Property<Direction> facing, Property<Boolean> triggered, List<Key> blocks, boolean whitelistMode) {
|
||||
super(customBlock);
|
||||
this.facingProperty = facing;
|
||||
this.triggeredProperty = triggered;
|
||||
this.blocks = blocks;
|
||||
this.whitelistMode = whitelistMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object state = args[0];
|
||||
Object level = args[1];
|
||||
Object pos = args[2];
|
||||
boolean hasNeighborSignal = FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, pos);
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return;
|
||||
boolean triggeredValue = blockState.get(this.triggeredProperty);
|
||||
if (hasNeighborSignal && !triggeredValue) {
|
||||
// FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(level, pos, thisBlock, 1, this.getTickPriority()); // 鬼知道为什么这个无法触发 tick
|
||||
tick(state, level, pos);
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, blockState.with(this.triggeredProperty, true).customBlockState().handle(), 2);
|
||||
} else if (!hasNeighborSignal && triggeredValue) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, blockState.with(this.triggeredProperty, false).customBlockState().handle(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
return state.owner().value().defaultState().with(this.facingProperty, context.getNearestLookingDirection().opposite());
|
||||
}
|
||||
|
||||
protected boolean blockCheckByBlockState(Object blockState) {
|
||||
if (blockState == null || FastNMS.INSTANCE.method$BlockStateBase$isAir(blockState)) {
|
||||
return false;
|
||||
}
|
||||
Key blockId = Optional.ofNullable(BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)))
|
||||
.filter(state -> !state.isEmpty())
|
||||
.map(state -> state.owner().value().id())
|
||||
.orElseGet(() -> BlockStateUtils.getBlockOwnerIdFromState(blockState));
|
||||
return blockCheckByKey(blockId);
|
||||
}
|
||||
|
||||
protected boolean blockCheckByKey(Key blockId) {
|
||||
return this.blocks.contains(blockId) == this.whitelistMode;
|
||||
}
|
||||
|
||||
protected abstract Object getTickPriority();
|
||||
|
||||
protected abstract void tick(Object state, Object level, Object pos);
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class PickaxeBlockBehavior extends FacingTriggerableBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public PickaxeBlockBehavior(CustomBlock customBlock, Property<Direction> facing, Property<Boolean> triggered, List<Key> blocks, boolean whitelistMode) {
|
||||
super(customBlock, facing, triggered, blocks, whitelistMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getTickPriority() {
|
||||
return CoreReflections.instance$TickPriority$EXTREMELY_HIGH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object level = args[1];
|
||||
Object pos = args[2];
|
||||
tick(state, level, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Object state, Object level, Object pos) {
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return;
|
||||
Object breakPos = FastNMS.INSTANCE.method$BlockPos$relative(pos, DirectionUtils.toNMSDirection(blockState.get(this.facingProperty)));
|
||||
Object breakState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, breakPos);
|
||||
if (blockCheckByBlockState(breakState)) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$destroyBlock(level, breakPos, true, null, 512);
|
||||
tryHandleDoubleBlock(level, breakState, breakPos);
|
||||
}
|
||||
}
|
||||
|
||||
private static void tryHandleDoubleBlock(Object level, Object state, Object blockPos) {
|
||||
int stateId = BlockStateUtils.blockStateToId(state);
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (blockState == null || blockState.isEmpty()) return;
|
||||
for (Property<?> property : blockState.getProperties()) {
|
||||
if (property.valueClass() != DoubleBlockHalf.class) continue;
|
||||
World world = BukkitWorldManager.instance().wrap(level);
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(LocationUtils.fromBlockPos(blockPos)));
|
||||
ContextHolder.Builder builder = ContextHolder.builder().withParameter(DirectContextParameters.POSITION, position);
|
||||
blockState.getDrops(builder, world, null).forEach(item -> world.dropItemNaturally(position, item));
|
||||
world.playBlockSound(position, blockState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Property<Direction> facing = (Property<Direction>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("facing"), "warning.config.block.behavior.pickaxe.missing_facing");
|
||||
Property<Boolean> triggered = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("triggered"), "warning.config.block.behavior.pickaxe.missing_triggered");
|
||||
boolean whitelistMode = (boolean) arguments.getOrDefault("whitelist", false);
|
||||
List<Key> blocks = MiscUtils.getAsStringList(arguments.get("blocks")).stream().map(Key::of).toList();
|
||||
if (blocks.isEmpty() && !whitelistMode) {
|
||||
blocks = FacingTriggerableBlockBehavior.DEFAULT_BLACKLIST_BLOCKS;
|
||||
}
|
||||
return new PickaxeBlockBehavior(block, facing, triggered, blocks, whitelistMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.PlaceBlockBlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PlaceBlockBehavior extends FacingTriggerableBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public PlaceBlockBehavior(CustomBlock customBlock, Property<Direction> facing, Property<Boolean> triggered, List<Key> blocks, boolean whitelistMode) {
|
||||
super(customBlock, facing, triggered, blocks, whitelistMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getTickPriority() {
|
||||
return CoreReflections.instance$TickPriority$EXTREMELY_LOW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object level = args[1];
|
||||
Object pos = args[2];
|
||||
tick(state, level, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Object state, Object level, Object nmsBlockPos) {
|
||||
BlockPos pos = LocationUtils.fromBlockPos(nmsBlockPos);
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return;
|
||||
Direction direction = blockState.get(this.facingProperty);
|
||||
Direction opposite = direction.opposite();
|
||||
BlockPos blockPos = pos.relative(opposite);
|
||||
BlockPos blockPos1 = pos.relative(direction);
|
||||
getItemAndDoThings(level, blockPos, opposite, itemStack -> {
|
||||
if (FastNMS.INSTANCE.method$ItemStack$isEmpty(itemStack)) {
|
||||
return false;
|
||||
} else {
|
||||
Object itemStack1 = FastNMS.INSTANCE.method$ItemStack$getItem(itemStack);
|
||||
boolean flag = false;
|
||||
if (CoreReflections.clazz$BlockItem.isInstance(itemStack1)) {
|
||||
Object block = FastNMS.INSTANCE.method$BlockItem$getBlock(itemStack1);
|
||||
if (blockCheckByBlockState(FastNMS.INSTANCE.method$Block$defaultState(block))) {
|
||||
Object blockHitResult = FastNMS.INSTANCE.constructor$BlockHitResult(
|
||||
FastNMS.INSTANCE.method$BlockPos$getCenter(LocationUtils.toBlockPos(blockPos1)),
|
||||
DirectionUtils.toNMSDirection(opposite),
|
||||
LocationUtils.toBlockPos(blockPos1),
|
||||
false
|
||||
);
|
||||
Object placeBlockBlockPlaceContext = FastNMS.INSTANCE.constructor$PlaceBlockBlockPlaceContext(
|
||||
level, CoreReflections.instance$InteractionHand$MAIN_HAND, itemStack, blockHitResult
|
||||
);
|
||||
Object interactionResult = FastNMS.INSTANCE.method$BlockItem$place(itemStack1, placeBlockBlockPlaceContext);
|
||||
flag = FastNMS.INSTANCE.method$InteractionResult$consumesAction(interactionResult);
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
Item<ItemStack> item = BukkitItemManager.instance().wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack));
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = item.getCustomItem();
|
||||
if (optionalCustomItem.isPresent()) {
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
for (ItemBehavior itemBehavior : customItem.behaviors()) {
|
||||
if (itemBehavior instanceof BlockItemBehavior blockItemBehavior) {
|
||||
if (!blockCheckByKey(blockItemBehavior.block())) continue;
|
||||
BlockHitResult hitResult = new BlockHitResult(
|
||||
LocationUtils.toVec3d(blockPos1),
|
||||
opposite,
|
||||
blockPos1,
|
||||
false
|
||||
);
|
||||
PlaceBlockBlockPlaceContext context = new PlaceBlockBlockPlaceContext(
|
||||
BukkitWorldManager.instance().wrap(level),
|
||||
InteractionHand.MAIN_HAND,
|
||||
BukkitItemManager.instance().wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack)),
|
||||
hitResult
|
||||
);
|
||||
InteractionResult result = blockItemBehavior.place(context);
|
||||
if (result.success()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
double d = FastNMS.INSTANCE.method$EntityType$getHeight(MEntityTypes.ITEM) / 2.0;
|
||||
double d1 = blockPos1.x() + 0.5;
|
||||
double d2 = blockPos1.y() + 0.5 - d;
|
||||
double d3 = blockPos1.z() + 0.5;
|
||||
Object itemEntity = FastNMS.INSTANCE.constructor$ItemEntity(level, d1, d2, d3, itemStack);
|
||||
FastNMS.INSTANCE.method$ItemEntity$setDefaultPickUpDelay(itemEntity);
|
||||
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(level, itemEntity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
private static boolean getItemAndDoThings(Object level, BlockPos blockPos, Direction direction, Function<Object, Boolean> function) {
|
||||
for (Object container : getContainersAt(level, blockPos)) {
|
||||
boolean flag = FastNMS.INSTANCE.method$HopperBlockEntity$getSlots(container, DirectionUtils.toNMSDirection(direction)).anyMatch(i -> {
|
||||
Object itemStack = FastNMS.INSTANCE.method$Container$removeItem(container, i, 1);
|
||||
if (!FastNMS.INSTANCE.method$ItemStack$isEmpty(itemStack)) {
|
||||
boolean flag1 = function.apply(FastNMS.INSTANCE.method$ItemStack$copy(itemStack));
|
||||
if (flag1) {
|
||||
FastNMS.INSTANCE.method$Container$setChanged(container);
|
||||
} else {
|
||||
FastNMS.INSTANCE.method$Container$setItem(container, i, itemStack);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (flag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Object itemAt = getItemAt(level, LocationUtils.toBlockPos(blockPos));
|
||||
if (itemAt != null) {
|
||||
Object item = FastNMS.INSTANCE.method$ItemEntity$getItem(itemAt);
|
||||
if (!FastNMS.INSTANCE.method$ItemStack$isEmpty(item)) {
|
||||
boolean flag = function.apply(FastNMS.INSTANCE.method$ItemStack$copyWithCount(item, 1));
|
||||
if (flag) {
|
||||
FastNMS.INSTANCE.method$ItemStack$shrink(item, 1);
|
||||
if (FastNMS.INSTANCE.method$ItemStack$getCount(item) <= 0) {
|
||||
FastNMS.INSTANCE.method$Entity$discard(itemAt);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> getContainersAt(Object level, BlockPos blockPos) {
|
||||
Object nmsBlockPos = LocationUtils.toBlockPos(blockPos);
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, nmsBlockPos);
|
||||
Object block = FastNMS.INSTANCE.method$BlockState$getBlock(blockState);
|
||||
if (CoreReflections.clazz$WorldlyContainerHolder.isInstance(block)) {
|
||||
Object container = FastNMS.INSTANCE.method$WorldlyContainerHolder$getContainer(block, blockState, level, nmsBlockPos);
|
||||
if (container != null) {
|
||||
return List.of(container);
|
||||
}
|
||||
} else if (FastNMS.INSTANCE.method$BlockStateBase$hasBlockEntity(blockState)) {
|
||||
Object blockEntity = FastNMS.INSTANCE.method$BlockGetter$getBlockEntity(level, nmsBlockPos);
|
||||
if (CoreReflections.clazz$Container.isInstance(blockEntity)) {
|
||||
if (!(CoreReflections.clazz$ChestBlockEntity.isInstance(blockEntity)) || !(CoreReflections.clazz$ChestBlock.isInstance(block))) {
|
||||
return List.of(blockEntity);
|
||||
}
|
||||
Object container = FastNMS.INSTANCE.method$ChestBlock$getContainer(block, blockState, level, nmsBlockPos, true);
|
||||
if (container != null) {
|
||||
return List.of(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (Object entity : (List<Object>) FastNMS.INSTANCE.method$EntityGetter$getEntities(
|
||||
level, null, blockAABB(nmsBlockPos),
|
||||
entity -> CoreReflections.clazz$Container.isInstance(entity) && FastNMS.INSTANCE.method$Entity$isAlive(entity))
|
||||
) {
|
||||
if (CoreReflections.clazz$Container.isInstance(entity)) {
|
||||
list.add(entity);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object getItemAt(Object level, Object blockPos) {
|
||||
List<Object> entitiesOfClass = (List<Object>) FastNMS.INSTANCE.method$EntityGetter$getEntitiesOfClass(
|
||||
level, CoreReflections.clazz$ItemEntity, blockAABB(blockPos), FastNMS.INSTANCE::method$Entity$isAlive
|
||||
);
|
||||
return entitiesOfClass.isEmpty() ? null : entitiesOfClass.getFirst();
|
||||
}
|
||||
|
||||
private static Object blockAABB(Object blockPos) {
|
||||
return FastNMS.INSTANCE.method$AABB$ofSize(FastNMS.INSTANCE.method$BlockPos$getCenter(blockPos), 0.9999999, 0.9999999, 0.9999999);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Property<Direction> facing = (Property<Direction>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("facing"), "warning.config.block.behavior.place_block.missing_facing");
|
||||
Property<Boolean> triggered = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("triggered"), "warning.config.block.behavior.place_block.missing_triggered");
|
||||
boolean whitelistMode = (boolean) arguments.getOrDefault("whitelist", false);
|
||||
List<Key> blocks = MiscUtils.getAsStringList(arguments.get("blocks")).stream().map(Key::of).toList();
|
||||
if (blocks.isEmpty() && !whitelistMode) {
|
||||
blocks = FacingTriggerableBlockBehavior.DEFAULT_BLACKLIST_BLOCKS;
|
||||
}
|
||||
return new PlaceBlockBehavior(block, facing, triggered, blocks, whitelistMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
|
||||
public class PlayerData<T> extends LivingEntityData<T> {
|
||||
public static final PlayerData<Float> PlayerAbsorption = new PlayerData<>(PlayerData.class, EntityDataValue.Serializers$FLOAT, 0.0f);
|
||||
public static final PlayerData<Integer> Score = new PlayerData<>(PlayerData.class, EntityDataValue.Serializers$INT, 0);
|
||||
public static final PlayerData<Byte> PlayerModeCustomisation = new PlayerData<>(PlayerData.class, EntityDataValue.Serializers$BYTE, (byte) 0);
|
||||
public static final PlayerData<Byte> PlayerMainHand = new PlayerData<>(PlayerData.class, EntityDataValue.Serializers$BYTE, (byte) 1);
|
||||
public static final PlayerData<Object> ShoulderLeft = new PlayerData<>(PlayerData.class, EntityDataValue.Serializers$COMPOUND_TAG, CoreReflections.instance$CompoundTag$Empty);
|
||||
public static final PlayerData<Object> ShoulderRight = new PlayerData<>(PlayerData.class, EntityDataValue.Serializers$COMPOUND_TAG, CoreReflections.instance$CompoundTag$Empty);
|
||||
|
||||
public PlayerData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,11 @@ package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.seat.BukkitSeatEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.BukkitNetworkManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.PlayerUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.ArrayUtils;
|
||||
@@ -21,7 +17,6 @@ import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
@@ -33,7 +28,6 @@ import org.joml.Vector3f;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitFurniture implements Furniture {
|
||||
private final Key id;
|
||||
@@ -56,7 +50,7 @@ public class BukkitFurniture implements Furniture {
|
||||
private final boolean hasExternalModel;
|
||||
// seats
|
||||
private final Set<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
|
||||
private final Map<Integer, BukkitSeatEntity> seats = Collections.synchronizedMap(new HashMap<>());
|
||||
private final Vector<WeakReference<Entity>> seats = new Vector<>();
|
||||
// cached spawn packet
|
||||
private Object cachedSpawnPacket;
|
||||
private Object cachedMinimizedSpawnPacket;
|
||||
@@ -196,13 +190,24 @@ public class BukkitFurniture implements Furniture {
|
||||
if (entity != null)
|
||||
entity.destroy();
|
||||
}
|
||||
destroySeats();
|
||||
for (WeakReference<Entity> r : this.seats) {
|
||||
Entity entity = r.get();
|
||||
if (entity == null) continue;
|
||||
for (Entity passenger : entity.getPassengers()) {
|
||||
entity.removePassenger(passenger);
|
||||
}
|
||||
entity.remove();
|
||||
}
|
||||
this.seats.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroySeats() {
|
||||
for (BukkitSeatEntity seat : this.seats.values()) {
|
||||
seat.destroy();
|
||||
for (WeakReference<Entity> entity : this.seats) {
|
||||
Entity e = entity.get();
|
||||
if (e != null) {
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
this.seats.clear();
|
||||
}
|
||||
@@ -290,17 +295,7 @@ public class BukkitFurniture implements Furniture {
|
||||
|
||||
@Override
|
||||
public void spawnSeatEntityForPlayer(net.momirealms.craftengine.core.entity.player.Player player, Seat seat) {
|
||||
BukkitSeatEntity seatEntity = (BukkitSeatEntity) seat.spawn(player, this);
|
||||
if (seatEntity == null) {
|
||||
this.removeOccupiedSeat(seat.offset());
|
||||
return;
|
||||
}
|
||||
this.seats.put(seatEntity.playerID(), seatEntity);
|
||||
player.setSeat(seatEntity);
|
||||
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) player;
|
||||
for (Player p : PlayerUtils.getTrackedBy(serverPlayer.platformPlayer())) {
|
||||
BukkitNetworkManager.instance().getOnlineUser(p).entityPacketHandlers().put(seatEntity.playerID(), seatEntity);
|
||||
}
|
||||
spawnSeatEntityForPlayer((Player) player.platformPlayer(), seat);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -323,31 +318,10 @@ public class BukkitFurniture implements Furniture {
|
||||
}
|
||||
}
|
||||
|
||||
public Location calculateSeatLocation(Seat seat) {
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate().transform(new Vector3f(seat.offset()));
|
||||
double yaw = seat.yaw() + this.location.getYaw();
|
||||
if (yaw < -180) yaw += 360;
|
||||
Location newLocation = this.location.clone();
|
||||
newLocation.setYaw((float) yaw);
|
||||
newLocation.add(offset.x, offset.y + 0.6, -offset.z);
|
||||
return newLocation;
|
||||
}
|
||||
|
||||
public BukkitSeatEntity seatByPlayerId(int playerId) {
|
||||
return this.seats.get(playerId);
|
||||
}
|
||||
|
||||
public void removeSeatEntity(int playerId) {
|
||||
this.seats.remove(playerId);
|
||||
}
|
||||
|
||||
public static Entity spawnSeatEntity(Furniture furniture, World world, Location loc, boolean limitPlayerRotation, Consumer<Entity> function) {
|
||||
EntityType type;
|
||||
if (limitPlayerRotation) {
|
||||
type = EntityType.ARMOR_STAND;
|
||||
loc = VersionHelper.isOrAbove1_20_2() ? loc.subtract(0, 0.9875, 0) : loc.subtract(0, 0.990625, 0);
|
||||
if (function == null) {
|
||||
function = entity -> {
|
||||
private void spawnSeatEntityForPlayer(org.bukkit.entity.Player player, Seat seat) {
|
||||
Location location = this.calculateSeatLocation(seat);
|
||||
Entity seatEntity = seat.limitPlayerRotation() ?
|
||||
EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location.subtract(0,0.9875,0) : location.subtract(0,0.990625,0), EntityType.ARMOR_STAND, entity -> {
|
||||
ArmorStand armorStand = (ArmorStand) entity;
|
||||
if (VersionHelper.isOrAbove1_21_3()) {
|
||||
Objects.requireNonNull(armorStand.getAttribute(Attribute.MAX_HEALTH)).setBaseValue(0.01);
|
||||
@@ -363,22 +337,29 @@ public class BukkitFurniture implements Furniture {
|
||||
armorStand.setAI(false);
|
||||
armorStand.setGravity(false);
|
||||
armorStand.setPersistent(false);
|
||||
armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, furniture.baseEntityId());
|
||||
// armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
||||
};
|
||||
}
|
||||
} else {
|
||||
type = EntityType.ITEM_DISPLAY;
|
||||
loc = VersionHelper.isOrAbove1_20_2() ? loc : loc.subtract(0, 0.25, 0);
|
||||
if (function == null) {
|
||||
function = entity -> {
|
||||
armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, this.baseEntityId());
|
||||
armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
||||
}) :
|
||||
EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location : location.subtract(0,0.25,0), EntityType.ITEM_DISPLAY, entity -> {
|
||||
ItemDisplay itemDisplay = (ItemDisplay) entity;
|
||||
itemDisplay.setPersistent(false);
|
||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, furniture.baseEntityId());
|
||||
// itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
||||
};
|
||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, this.baseEntityId());
|
||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
||||
});
|
||||
this.seats.add(new WeakReference<>(seatEntity));
|
||||
if (!seatEntity.addPassenger(player)) {
|
||||
seatEntity.remove();
|
||||
this.removeOccupiedSeat(seat.offset());
|
||||
}
|
||||
}
|
||||
return EntityUtils.spawnEntity(world, loc, type, function);
|
||||
|
||||
private Location calculateSeatLocation(Seat seat) {
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate().transform(new Vector3f(seat.offset()));
|
||||
double yaw = seat.yaw() + this.location.getYaw();
|
||||
if (yaw < -180) yaw += 360;
|
||||
Location newLocation = this.location.clone();
|
||||
newLocation.setYaw((float) yaw);
|
||||
newLocation.add(offset.x, offset.y + 0.6, -offset.z);
|
||||
return newLocation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBox;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.seat.BukkitSeatEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
@@ -12,10 +10,10 @@ import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.*;
|
||||
@@ -25,6 +23,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
@@ -38,6 +37,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY);
|
||||
public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_EXTRA_DATA_KEY);
|
||||
public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY);
|
||||
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY);
|
||||
public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION);
|
||||
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
|
||||
public static Object NMS_COLLISION_ENTITY_TYPE = MEntityTypes.INTERACTION;
|
||||
@@ -97,8 +97,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.javaPlugin());
|
||||
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin());
|
||||
if (VersionHelper.isFolia()) {
|
||||
BiConsumer<Entity, Runnable> taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {
|
||||
});
|
||||
BiConsumer<Entity, Runnable> taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {});
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
@@ -337,32 +336,20 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
}
|
||||
|
||||
protected void tryLeavingSeat(@NotNull Player player, @NotNull Entity vehicle) {
|
||||
net.momirealms.craftengine.core.entity.player.Player serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer == null) {
|
||||
Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
||||
if (baseFurniture == null) return;
|
||||
vehicle.remove();
|
||||
BukkitFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture);
|
||||
if (furniture == null) {
|
||||
vehicle.remove();
|
||||
return;
|
||||
}
|
||||
SeatEntity seatEntity = furniture.seatByPlayerId(player.getEntityId());
|
||||
if (seatEntity != null && !seatEntity.destroyed()) {
|
||||
seatEntity.destroy();
|
||||
}
|
||||
String vector3f = vehicle.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING);
|
||||
if (vector3f == null) {
|
||||
plugin.logger().warn("Failed to get vector3f for player " + player.getName() + "'s seat");
|
||||
return;
|
||||
}
|
||||
|
||||
BukkitSeatEntity seatEntity = (BukkitSeatEntity) serverPlayer.seat();
|
||||
if (seatEntity == null || seatEntity.literalObject() != vehicle) return;
|
||||
|
||||
BukkitFurniture furniture = seatEntity.furniture();
|
||||
if (furniture == null) {
|
||||
seatEntity.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
seatEntity.dismount(serverPlayer);
|
||||
Vector3f seatPos = MiscUtils.getAsVector3f(vector3f, "seat");
|
||||
furniture.removeOccupiedSeat(seatPos);
|
||||
|
||||
if (player.getVehicle() != null) return;
|
||||
Location vehicleLocation = vehicle.getLocation();
|
||||
@@ -427,8 +414,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(bukkitEntity);
|
||||
return FastNMS.INSTANCE.method$Entity$canBeCollidedWith(nmsEntity);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
@@ -12,9 +10,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerAnimationEvent;
|
||||
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||
@@ -127,30 +123,12 @@ public class FurnitureEventListener implements Listener {
|
||||
|
||||
// do not allow players to put item on seats
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onInteractArmorStand(PlayerArmorStandManipulateEvent event) {
|
||||
ArmorStand clicked = event.getRightClicked();
|
||||
Integer baseFurniture = clicked.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
||||
public void onInteractArmorStand(PlayerInteractAtEntityEvent event) {
|
||||
Entity clicked = event.getRightClicked();
|
||||
if (clicked instanceof ArmorStand armorStand) {
|
||||
Integer baseFurniture = armorStand.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
||||
if (baseFurniture == null) return;
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onMainHandChange(PlayerItemHeldEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.getVehicle() == null) return;
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer.seat() == null) return;
|
||||
|
||||
serverPlayer.seat().event(serverPlayer, event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerAnimation(PlayerAnimationEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.getVehicle() == null) return;
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer.seat() == null) return;
|
||||
|
||||
serverPlayer.seat().event(serverPlayer, event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.seat;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public abstract class BukkitSeatEntity extends BukkitEntity implements SeatEntity {
|
||||
private final BukkitFurniture furniture;
|
||||
private final Vector3f vector3f;
|
||||
private final int playerID;
|
||||
private boolean destroyed = false;
|
||||
|
||||
public BukkitSeatEntity(Entity entity, Furniture furniture, Vector3f vector3f, int playerID) {
|
||||
super(entity);
|
||||
this.furniture = (BukkitFurniture) furniture;
|
||||
this.vector3f = vector3f;
|
||||
this.playerID = playerID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(NetWorkUser to) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismount(Player player) {
|
||||
if (player == null) return;
|
||||
player.setSeat(null);
|
||||
onDismount(player);
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismount(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(Player player, Object event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (destroyed) return;
|
||||
destroyed = true;
|
||||
|
||||
org.bukkit.entity.Entity entity = this.literalObject();
|
||||
if (entity == null) return;
|
||||
|
||||
for (org.bukkit.entity.Entity passenger : entity.getPassengers()) {
|
||||
entity.removePassenger(passenger);
|
||||
if (passenger instanceof org.bukkit.entity.Player p && p.getEntityId() == this.playerID) {
|
||||
Player cePlayer = BukkitAdaptors.adapt(p);
|
||||
dismount(cePlayer);
|
||||
}
|
||||
}
|
||||
entity.remove();
|
||||
furniture.removeSeatEntity(playerID());
|
||||
furniture.removeOccupiedSeat(vector3f());
|
||||
}
|
||||
|
||||
public boolean destroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitFurniture furniture() {
|
||||
return this.furniture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f vector3f() {
|
||||
return this.vector3f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int playerID() {
|
||||
return this.playerID;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.seat;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.SeatType;
|
||||
|
||||
public class BukkitSeatTypes extends SeatType {
|
||||
|
||||
public static void init() {
|
||||
register(SIT, SitSeat.FACTORY);
|
||||
register(LAY, LaySeat.FACTORY);
|
||||
register(CRAWL, CrawlSeat.FACTORY);
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.seat;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.PlayerData;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.ShulkerData;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.BukkitNetworkManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.PlayerUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Pose;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CrawlSeat extends AbstractSeat {
|
||||
public static final SeatFactory FACTORY = new Factory();
|
||||
private static final List<Object> visualData = new ArrayList<>();
|
||||
private final boolean limitPlayerRotation;
|
||||
|
||||
static {
|
||||
ShulkerData.NoGravity.addEntityDataIfNotDefaultValue(true, visualData);
|
||||
ShulkerData.Silent.addEntityDataIfNotDefaultValue(true, visualData);
|
||||
ShulkerData.MobFlags.addEntityDataIfNotDefaultValue((byte) 0x01, visualData);
|
||||
ShulkerData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, visualData);
|
||||
}
|
||||
|
||||
public CrawlSeat(Vector3f offset, float yaw, boolean limitPlayerRotation) {
|
||||
super(offset, yaw);
|
||||
this.limitPlayerRotation = limitPlayerRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeatEntity spawn(Player player, Furniture furniture) {
|
||||
return spawn((org.bukkit.entity.Player) player.platformPlayer(), furniture);
|
||||
}
|
||||
|
||||
public SeatEntity spawn(org.bukkit.entity.Player player, Furniture furniture) {
|
||||
Location location = ((BukkitFurniture) furniture).calculateSeatLocation(this);
|
||||
|
||||
org.bukkit.entity.Entity seatEntity = BukkitFurniture.spawnSeatEntity(furniture, player.getWorld(), location, this.limitPlayerRotation, null);
|
||||
if (!seatEntity.addPassenger(player)) {
|
||||
seatEntity.remove();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fix Rider Pose
|
||||
int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
List<Object> packets = new ArrayList<>();
|
||||
packets.add(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(entityId, UUID.randomUUID(), location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw(),
|
||||
MEntityTypes.SHULKER, 0, CoreReflections.instance$Vec3$Zero, 0));
|
||||
packets.add(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, List.copyOf(visualData)));
|
||||
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object attributeInstance = CoreReflections.constructor$AttributeInstance.newInstance(MAttributeHolders.SCALE, (Consumer<?>) (o) -> {
|
||||
});
|
||||
CoreReflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, 0.6);
|
||||
packets.add(
|
||||
NetworkReflections.constructor$ClientboundUpdateAttributesPacket0
|
||||
.newInstance(entityId, Collections.singletonList(attributeInstance))
|
||||
);
|
||||
packets.add(FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(seatEntity.getEntityId(), entityId));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to add crawl seat attributes", e);
|
||||
}
|
||||
|
||||
Object bundle = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
serverPlayer.sendPacket(bundle, true);
|
||||
|
||||
// Sync Pose
|
||||
player.setPose(Pose.SWIMMING, true);
|
||||
Object syncPosePacket = null;
|
||||
try {
|
||||
Object playerData = CoreReflections.method$Entity$getEntityData.invoke(serverPlayer.serverPlayer());
|
||||
Object dataItem = CoreReflections.method$SynchedEntityData$getItem.invoke(playerData, PlayerData.Pose.entityDataAccessor());
|
||||
Object dataValue = CoreReflections.method$SynchedEntityData$DataItem$value.invoke(dataItem);
|
||||
syncPosePacket = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(serverPlayer.entityID(), List.of(dataValue));
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to construct sync pose packet", e);
|
||||
}
|
||||
|
||||
Object finalSyncPosePacket = syncPosePacket;
|
||||
BukkitCraftEngine.instance().scheduler().sync().runLater(() -> {
|
||||
serverPlayer.sendPacket(finalSyncPosePacket, true);
|
||||
for (org.bukkit.entity.Player p : PlayerUtils.getTrackedBy(player)) {
|
||||
BukkitNetworkManager.instance().sendPacket(BukkitAdaptors.adapt(p), finalSyncPosePacket, true);
|
||||
}
|
||||
}, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
|
||||
return new CrawlEntity(seatEntity, furniture, offset(), player.getEntityId(), entityId, syncPosePacket);
|
||||
}
|
||||
|
||||
private static class CrawlEntity extends BukkitSeatEntity {
|
||||
private final int entityId;
|
||||
private final Object syncPosePacket;
|
||||
|
||||
|
||||
public CrawlEntity(Entity entity, Furniture furniture, Vector3f vector3f, int playerID, int entityId, Object fixPosePacket) {
|
||||
super(entity, furniture, vector3f, playerID);
|
||||
this.entityId = entityId;
|
||||
this.syncPosePacket = fixPosePacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(NetWorkUser to) {
|
||||
to.sendPacket(syncPosePacket, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismount(Player player) {
|
||||
if (player == null) return;
|
||||
org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.platformPlayer();
|
||||
bukkitPlayer.setPose(Pose.STANDING, false);
|
||||
try {
|
||||
Object packet = NetworkReflections.constructor$ClientboundRemoveEntitiesPacket.newInstance((Object) new int[]{entityId});
|
||||
player.sendPacket(packet, false);
|
||||
} catch (Exception e) {
|
||||
BukkitCraftEngine.instance().logger().warn("Failed to dismount from CrawlEntity", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return SeatType.CRAWL;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements SeatFactory {
|
||||
|
||||
@Override
|
||||
public Seat create(List<String> args) {
|
||||
if (args.size() == 1) return new CrawlSeat(MiscUtils.getAsVector3f(args.getFirst(), "seats"), 0, false);
|
||||
return new CrawlSeat(MiscUtils.getAsVector3f(args.getFirst(), "seats"), Float.parseFloat(args.get(1)), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,698 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.seat;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.LivingEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.PlayerData;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.BukkitNetworkManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MItems;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.scheduler.impl.FoliaTask;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.entity.EquipmentSlot;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.NMSPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerAnimationEvent;
|
||||
import org.bukkit.event.player.PlayerAnimationType;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static net.momirealms.craftengine.core.plugin.network.ProtocolVersion.V1_21_2;
|
||||
|
||||
public class LaySeat extends AbstractSeat {
|
||||
public static final SeatFactory FACTORY = new Factory();
|
||||
private static final List<Pair<Object, Object>> emptyEquipments;
|
||||
private static final List<Pair<Object, ItemStack>> emptyBukkitEquipments;
|
||||
private static Method method$InventoryView$convertSlot;
|
||||
private static Method method$InventoryView$getTopInventory;
|
||||
private static Method method$InventoryView$getType;
|
||||
private final Direction facing;
|
||||
private final boolean sleep;
|
||||
private final boolean phantom;
|
||||
|
||||
static {
|
||||
if (!VersionHelper.isOrAbove1_21_1()) {
|
||||
method$InventoryView$convertSlot = ReflectionUtils.getMethod(InventoryView.class, new String[]{"convertSlot"}, int.class);
|
||||
method$InventoryView$getTopInventory = ReflectionUtils.getMethod(InventoryView.class, new String[]{"getTopInventory"});
|
||||
method$InventoryView$getType = ReflectionUtils.getMethod(Inventory.class, new String[]{"getType"});
|
||||
}
|
||||
emptyEquipments = List.of(
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$MAINHAND, MItems.AIR$Item),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$OFFHAND, MItems.AIR$Item),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$HEAD, MItems.AIR$Item),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$CHEST, MItems.AIR$Item),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$LEGS, MItems.AIR$Item),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$FEET, MItems.AIR$Item)
|
||||
);
|
||||
emptyBukkitEquipments = List.of(
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$MAINHAND, ItemUtils.AIR),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$OFFHAND, ItemUtils.AIR),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$HEAD, ItemUtils.AIR),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$CHEST, ItemUtils.AIR),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$LEGS, ItemUtils.AIR),
|
||||
Pair.of(CoreReflections.instance$EquipmentSlot$FEET, ItemUtils.AIR)
|
||||
);
|
||||
}
|
||||
|
||||
public LaySeat(Vector3f offset, Direction facing, boolean sleep, boolean phantom) {
|
||||
super(offset, 0);
|
||||
this.facing = facing;
|
||||
this.sleep = sleep;
|
||||
this.phantom = phantom;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public SeatEntity spawn(Player cePlayer, Furniture furniture) {
|
||||
Location loc = ((BukkitFurniture) furniture).calculateSeatLocation(this);
|
||||
|
||||
org.bukkit.entity.Player player = (org.bukkit.entity.Player) cePlayer.platformPlayer();
|
||||
Object serverPlayer = cePlayer.serverPlayer();
|
||||
|
||||
// Pose offset nearly same as vanilla
|
||||
AttributeInstance attribute = VersionHelper.isOrAbove1_21_2() ? player.getAttribute(Attribute.SCALE) : null;
|
||||
double scale = attribute == null ? 1 : attribute.getValue();
|
||||
loc.add(0, 0.08525 * scale, 0);
|
||||
|
||||
try {
|
||||
List<Object> packets = new ArrayList<>();
|
||||
// NPC
|
||||
Object server = CoreReflections.method$MinecraftServer$getServer.invoke(null);
|
||||
Object level = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld());
|
||||
UUID uuid = UUID.randomUUID();
|
||||
Object npcProfile = CoreReflections.constructor$GameProfile.newInstance(uuid, player.getName());
|
||||
Object playerProfile = CoreReflections.method$ServerPlayer$getGameProfile.invoke(serverPlayer);
|
||||
|
||||
Multimap<String, Object> properties = (Multimap<String, Object>) CoreReflections.method$GameProfile$getProperties.invoke(npcProfile);
|
||||
properties.putAll((Multimap<String, Object>) CoreReflections.method$GameProfile$getProperties.invoke(playerProfile));
|
||||
|
||||
Object npc;
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
Object clientInfo = CoreReflections.method$ServerPlayer$clientInformation.invoke(serverPlayer);
|
||||
npc = CoreReflections.constructor$ServerPlayer.newInstance(server, level, npcProfile, clientInfo);
|
||||
} else {
|
||||
npc = CoreReflections.constructor$ServerPlayer.newInstance(server, level, npcProfile);
|
||||
}
|
||||
int npcId = FastNMS.INSTANCE.method$Entity$getId(npc);
|
||||
CoreReflections.method$Entity$absSnapTo.invoke(npc, loc.getX(), loc.getY(), loc.getZ(), 0, 0);
|
||||
Object npcSpawnPacket;
|
||||
if (!VersionHelper.isOrAbove1_20_2()) {
|
||||
npcSpawnPacket = NetworkReflections.constructor$ClientboundAddPlayerPacket.newInstance(npc);
|
||||
} else {
|
||||
npcSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(npcId, uuid,
|
||||
loc.getX(), loc.getY(), loc.getZ(), 0, 0,
|
||||
MEntityTypes.PLAYER, 0, CoreReflections.instance$Vec3$Zero, 0);
|
||||
}
|
||||
|
||||
// Info
|
||||
EnumSet enumSet = EnumSet.noneOf((Class<? extends Enum>) NetworkReflections.clazz$ClientboundPlayerInfoUpdatePacket$Action);
|
||||
enumSet.add(NetworkReflections.instance$ClientboundPlayerInfoUpdatePacket$Action$ADD_PLAYER);
|
||||
Object entry;
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
entry = NetworkReflections.constructor$ClientBoundPlayerInfoUpdatePacket$Entry.newInstance(
|
||||
uuid, npcProfile, false, 0, CoreReflections.instance$GameType$SURVIVAL, null, true, 0, null);
|
||||
} else if (VersionHelper.isOrAbove1_21_3()) {
|
||||
entry = NetworkReflections.constructor$ClientBoundPlayerInfoUpdatePacket$Entry.newInstance(
|
||||
uuid, npcProfile, false, 0, CoreReflections.instance$GameType$SURVIVAL, null, 0, null);
|
||||
} else {
|
||||
entry = NetworkReflections.constructor$ClientBoundPlayerInfoUpdatePacket$Entry.newInstance(
|
||||
uuid, npcProfile, false, 0, CoreReflections.instance$GameType$SURVIVAL, null, null);
|
||||
}
|
||||
Object npcInfoPacket = FastNMS.INSTANCE.constructor$ClientboundPlayerInfoUpdatePacket(enumSet, Collections.singletonList(entry));
|
||||
|
||||
// Bed
|
||||
Direction bedDir = Direction.fromYaw(loc.getYaw() + Direction.getYaw(facing));
|
||||
if (bedDir == Direction.EAST || bedDir == Direction.WEST) bedDir = bedDir.opposite();
|
||||
BlockData bedData = Material.WHITE_BED.createBlockData("[facing=" + bedDir.name().toLowerCase() + ",part=head]");
|
||||
Location bedLoc = loc.clone();
|
||||
bedLoc.setY(bedLoc.getWorld().getMinHeight());
|
||||
Object bedPos = LocationUtils.toBlockPos(new BlockPos(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ()));
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(bedData);
|
||||
Object bedPacket = NetworkReflections.constructor$ClientboundBlockUpdatePacket.newInstance(bedPos, blockState);
|
||||
|
||||
// Data
|
||||
Object npcData = CoreReflections.method$Entity$getEntityData.invoke(npc);
|
||||
Object playerData = CoreReflections.method$Entity$getEntityData.invoke(serverPlayer);
|
||||
CoreReflections.method$Entity$setInvisible.invoke(serverPlayer, true);
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(npcData, PlayerData.Pose.entityDataAccessor(), CoreReflections.instance$Pose$SLEEPING);
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(npcData, LivingEntityData.SleepingPos.entityDataAccessor(), Optional.of(bedPos));
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(npcData, PlayerData.PlayerModeCustomisation.entityDataAccessor(), CoreReflections.method$SynchedEntityData$get.invoke(playerData, PlayerData.PlayerModeCustomisation.entityDataAccessor()));
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(npcData, PlayerData.PlayerMainHand.entityDataAccessor(), CoreReflections.method$SynchedEntityData$get.invoke(playerData, PlayerData.PlayerMainHand.entityDataAccessor()));
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(npcData, PlayerData.ShoulderLeft.entityDataAccessor(), CoreReflections.method$SynchedEntityData$get.invoke(playerData, PlayerData.ShoulderLeft.entityDataAccessor()));
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(npcData, PlayerData.ShoulderRight.entityDataAccessor(), CoreReflections.method$SynchedEntityData$get.invoke(playerData, PlayerData.ShoulderRight.entityDataAccessor()));
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(playerData, PlayerData.ShoulderLeft.entityDataAccessor(), CoreReflections.instance$CompoundTag$Empty);
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(playerData, PlayerData.ShoulderRight.entityDataAccessor(), CoreReflections.instance$CompoundTag$Empty);
|
||||
|
||||
// SetData
|
||||
CoreReflections.method$Entity$setInvisible.invoke(serverPlayer, true);
|
||||
Object npcDataPacket = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(
|
||||
npcId, (List) CoreReflections.method$SynchedEntityData$packDirty.invoke(npcData)
|
||||
);
|
||||
|
||||
// Remove
|
||||
Object npcRemovePacket = NetworkReflections.constructor$ClientboundRemoveEntitiesPacket.newInstance((Object) new int[]{npcId});
|
||||
|
||||
// TP
|
||||
Object npcTeleportPacket;
|
||||
if (VersionHelper.isOrAbove1_21_3()) {
|
||||
Object positionMoveRotation = CoreReflections.method$PositionMoveRotation$of.invoke(null, npc);
|
||||
npcTeleportPacket = NetworkReflections.constructor$ClientboundTeleportEntityPacket.newInstance(npcId, positionMoveRotation, Set.of(), false);
|
||||
} else {
|
||||
npcTeleportPacket = NetworkReflections.constructor$ClientboundTeleportEntityPacket.newInstance(npc);
|
||||
}
|
||||
|
||||
// Equipment
|
||||
Object emptyEquipPacket = NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(player.getEntityId(), emptyEquipments);
|
||||
|
||||
Map<EquipmentSlot, ItemStack> equipments = new HashMap<>();
|
||||
EntityEquipment equipment = player.getEquipment();
|
||||
for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) {
|
||||
if ((!slot.isHand() && !slot.isArmor())
|
||||
|| (VersionHelper.isOrAbove1_20_5() && slot == org.bukkit.inventory.EquipmentSlot.BODY)) {
|
||||
continue;
|
||||
}
|
||||
EquipmentSlot slotId = EntityUtils.toCEEquipmentSlot(slot);
|
||||
ItemStack item = equipment.getItem(slot);
|
||||
equipments.put(slotId, item);
|
||||
}
|
||||
List<Pair<Object, Object>> npcSlots = new ArrayList<>();
|
||||
equipments.forEach((slot, item) -> npcSlots.add(Pair.of(EntityUtils.fromEquipmentSlot(slot), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(item))));
|
||||
Object fullEquipPacket = NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(npcId, npcSlots);
|
||||
|
||||
// Animation
|
||||
Object npcLeftAnimatePacket = NetworkReflections.constructor$ClientboundAnimatePacket.newInstance(npc, 0);
|
||||
Object npcRightAnimatePacket = NetworkReflections.constructor$ClientboundAnimatePacket.newInstance(npc, 3);
|
||||
|
||||
packets.add(npcInfoPacket);
|
||||
packets.add(npcSpawnPacket);
|
||||
packets.add(bedPacket);
|
||||
packets.add(npcDataPacket);
|
||||
packets.add(npcTeleportPacket);
|
||||
packets.add(emptyEquipPacket);
|
||||
packets.add(npcLeftAnimatePacket);
|
||||
Object npcInitPackets = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||
|
||||
// Spawn
|
||||
org.bukkit.entity.Entity seatEntity = BukkitFurniture.spawnSeatEntity(furniture, player.getWorld(), loc, false, null);
|
||||
if (!seatEntity.addPassenger(player)) { // 0.5 higher
|
||||
seatEntity.remove();
|
||||
return null;
|
||||
}
|
||||
cePlayer.sendPacket(npcInitPackets, true);
|
||||
cePlayer.sendPacket(fullEquipPacket, true);
|
||||
if (player.getY() > 0 && cePlayer.protocolVersion().isVersionNewerThan(V1_21_2)) {
|
||||
BukkitCraftEngine.instance().scheduler().asyncLater(() -> cePlayer.sendPacket(npcTeleportPacket, true),
|
||||
50, TimeUnit.MILLISECONDS); // over height 0 cost 2 npcTeleportPacket
|
||||
}
|
||||
|
||||
Set<NetWorkUser> trackers = new HashSet<>();
|
||||
for (org.bukkit.entity.Player o : PlayerUtils.getTrackedBy(player)) {
|
||||
NetWorkUser tracker = BukkitNetworkManager.instance().getOnlineUser(o);
|
||||
tracker.sendPacket(npcInitPackets, false);
|
||||
tracker.sendPacket(fullEquipPacket, false);
|
||||
if (player.getY() > 0 && tracker.protocolVersion().isVersionNewerThan(V1_21_2)) {
|
||||
BukkitCraftEngine.instance().scheduler().asyncLater(() -> tracker.sendPacket(npcTeleportPacket, false),
|
||||
50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
trackers.add(tracker);
|
||||
}
|
||||
|
||||
// HeadRot
|
||||
Direction npcDir = bedDir.opposite();
|
||||
|
||||
if (sleep) {
|
||||
player.setSleepingIgnored(true);
|
||||
}
|
||||
|
||||
if (phantom) {
|
||||
player.setStatistic(Statistic.TIME_SINCE_REST, 0);
|
||||
}
|
||||
|
||||
return new LayEntity(
|
||||
seatEntity,
|
||||
furniture,
|
||||
this.offset(),
|
||||
npcInitPackets,
|
||||
npcRemovePacket,
|
||||
npcTeleportPacket,
|
||||
npcLeftAnimatePacket,
|
||||
npcRightAnimatePacket,
|
||||
(BukkitServerPlayer) cePlayer,
|
||||
trackers,
|
||||
bedLoc,
|
||||
npc,
|
||||
npcId,
|
||||
npcDir,
|
||||
equipments,
|
||||
emptyEquipPacket,
|
||||
fullEquipPacket,
|
||||
sleep
|
||||
);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to spawn LaySeat", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class LayEntity extends BukkitSeatEntity {
|
||||
private final Object npcInitPackets;
|
||||
private final Object npcRemovePacket;
|
||||
private final Object npcTPPacket;
|
||||
private final Object npcLeftAnimatePacket;
|
||||
private final Object npcRightAnimatePacket;
|
||||
private final BukkitServerPlayer serverPlayer;
|
||||
private final Object npc;
|
||||
private final Location bedLoc;
|
||||
private final int npcID;
|
||||
private final Direction npcDir;
|
||||
private final Set<NetWorkUser> trackers;
|
||||
|
||||
// Equipment
|
||||
private final PlayerMonitorTask task;
|
||||
private final Map<EquipmentSlot, ItemStack> equipments;
|
||||
private final Object emptyEquipPacket;
|
||||
private Object updateEquipPacket;
|
||||
private Object fullEquipPacket;
|
||||
|
||||
private final boolean sleep;
|
||||
private Object npcRotHeadPacket;
|
||||
private Object npcDataPacket;
|
||||
|
||||
public LayEntity(
|
||||
org.bukkit.entity.Entity entity,
|
||||
Furniture furniture,
|
||||
Vector3f vector,
|
||||
Object npcInitPackets,
|
||||
Object npcRemovePacket,
|
||||
Object npcTPPacket,
|
||||
Object npcLeftAnimatePacket,
|
||||
Object npcRightAnimatePacket,
|
||||
BukkitServerPlayer serverPlayer,
|
||||
Set<NetWorkUser> trackers,
|
||||
Location bedLoc,
|
||||
Object npc,
|
||||
int npcID,
|
||||
Direction npcDir,
|
||||
Map<EquipmentSlot, ItemStack> equipments,
|
||||
Object emptyEquipPacket,
|
||||
Object fullEquipPacket,
|
||||
boolean sleep
|
||||
) {
|
||||
super(entity, furniture, vector, serverPlayer.entityID());
|
||||
this.npcInitPackets = npcInitPackets;
|
||||
this.npcRemovePacket = npcRemovePacket;
|
||||
this.npcTPPacket = npcTPPacket;
|
||||
this.npcLeftAnimatePacket = npcLeftAnimatePacket;
|
||||
this.npcRightAnimatePacket = npcRightAnimatePacket;
|
||||
this.serverPlayer = serverPlayer;
|
||||
this.trackers = trackers;
|
||||
this.bedLoc = bedLoc;
|
||||
this.npc = npc;
|
||||
this.npcID = npcID;
|
||||
this.npcDir = npcDir;
|
||||
|
||||
this.task = new PlayerMonitorTask();
|
||||
this.equipments = equipments;
|
||||
this.emptyEquipPacket = emptyEquipPacket;
|
||||
this.fullEquipPacket = fullEquipPacket;
|
||||
|
||||
this.sleep = sleep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(NetWorkUser to) {
|
||||
to.sendPacket(this.npcInitPackets, false);
|
||||
to.sendPacket(this.fullEquipPacket, false);
|
||||
to.sendPacket(this.npcRotHeadPacket, false);
|
||||
if (npcDataPacket != null) to.sendPacket(this.npcDataPacket, false);
|
||||
if (serverPlayer.y() > 0 && to.protocolVersion().isVersionNewerThan(V1_21_2)) {
|
||||
BukkitCraftEngine.instance().scheduler().asyncLater(() ->
|
||||
to.sendPacket(this.npcTPPacket, false), 50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
trackers.add(to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleEntitiesRemove(NetWorkUser user, IntList entityIds) {
|
||||
entityIds.add(npcID);
|
||||
trackers.remove(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismount(Player player) {
|
||||
super.dismount(player);
|
||||
if (player != null) return;
|
||||
try { // for disconnect recover
|
||||
Object blockPos = LocationUtils.toBlockPos(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ());
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(bedLoc.getBlock().getBlockData());
|
||||
Object blockRecoverPacket = NetworkReflections.constructor$ClientboundBlockUpdatePacket.newInstance(blockPos, blockState);
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(blockRecoverPacket, false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to dismount player", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismount(Player player) {
|
||||
this.task.task.cancel();
|
||||
|
||||
org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.platformPlayer();
|
||||
Object blockPos = LocationUtils.toBlockPos(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ());
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(bedLoc.getBlock().getBlockData());
|
||||
|
||||
try {
|
||||
Object blockRecoverPacket = NetworkReflections.constructor$ClientboundBlockUpdatePacket.newInstance(blockPos, blockState);
|
||||
player.sendPacket(this.npcRemovePacket, true);
|
||||
player.sendPacket(blockRecoverPacket, true);
|
||||
|
||||
if (bukkitPlayer.getPotionEffect(PotionEffectType.INVISIBILITY) == null) {
|
||||
CoreReflections.method$Entity$setInvisible.invoke(serverPlayer.serverPlayer(), false);
|
||||
}
|
||||
|
||||
Object npcData = CoreReflections.method$Entity$getEntityData.invoke(npc);
|
||||
Object playerData = CoreReflections.method$Entity$getEntityData.invoke(serverPlayer.serverPlayer());
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(
|
||||
playerData,
|
||||
PlayerData.ShoulderLeft.entityDataAccessor(),
|
||||
CoreReflections.method$SynchedEntityData$get.invoke(npcData, PlayerData.ShoulderLeft.entityDataAccessor())
|
||||
);
|
||||
CoreReflections.method$SynchedEntityData$set.invoke(
|
||||
playerData,
|
||||
PlayerData.ShoulderRight.entityDataAccessor(),
|
||||
CoreReflections.method$SynchedEntityData$get.invoke(npcData, PlayerData.ShoulderRight.entityDataAccessor())
|
||||
);
|
||||
|
||||
bukkitPlayer.updateInventory();
|
||||
|
||||
if (sleep) {
|
||||
bukkitPlayer.setSleepingIgnored(false);
|
||||
}
|
||||
|
||||
Object fullSlots = NetworkReflections.method$ClientboundSetEquipmentPacket$getSlots.invoke(this.fullEquipPacket);
|
||||
Object recoverEquip = NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(bukkitPlayer.getEntityId(), fullSlots);
|
||||
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(this.npcRemovePacket, false);
|
||||
tracker.sendPacket(blockRecoverPacket, false);
|
||||
tracker.sendPacket(recoverEquip, false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to dismount from LayEntity", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void equipmentChange(Map<EquipmentSlot, ItemStack> equipmentChanges, int previousSlot) {
|
||||
org.bukkit.entity.Player player = serverPlayer.platformPlayer();
|
||||
List<Pair<Object, Object>> changedSlots = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<EquipmentSlot, ItemStack> entry : equipmentChanges.entrySet()) {
|
||||
Object slotId = EntityUtils.fromEquipmentSlot(entry.getKey());
|
||||
Object itemStack = FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(entry.getValue());
|
||||
changedSlots.add(Pair.of(slotId, itemStack));
|
||||
}
|
||||
this.equipments.putAll(equipmentChanges);
|
||||
|
||||
List<Pair<Object, Object>> allSlots = new ArrayList<>();
|
||||
equipments.forEach((slot, item) ->
|
||||
allSlots.add(Pair.of(EntityUtils.fromEquipmentSlot(slot), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(item))));
|
||||
try {
|
||||
this.updateEquipPacket = NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(npcID, changedSlots);
|
||||
this.fullEquipPacket = NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(npcID, allSlots);
|
||||
if (previousSlot != -1) {
|
||||
player.updateInventory();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle equipmentChange", e);
|
||||
}
|
||||
|
||||
serverPlayer.sendPacket(this.emptyEquipPacket, false);
|
||||
serverPlayer.sendPacket(this.updateEquipPacket, false);
|
||||
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(this.updateEquipPacket, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSetEquipment(NetWorkUser user, ByteBufPacketEvent event, Object slots) {
|
||||
if (emptyBukkitEquipments.equals(slots)) return;
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleContainerSetSlot(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||
try {
|
||||
int slot = (int) NetworkReflections.method$ClientboundContainerSetSlotPacket$getSlot.invoke(packet);
|
||||
org.bukkit.entity.Player player = (org.bukkit.entity.Player) user.platformPlayer();
|
||||
|
||||
int convertSlot;
|
||||
boolean isPlayerInv;
|
||||
|
||||
if (!VersionHelper.isOrAbove1_21_1()) {
|
||||
Object openInventory = player.getOpenInventory();
|
||||
convertSlot = (int) method$InventoryView$convertSlot.invoke(openInventory, slot);
|
||||
Object topInventory = method$InventoryView$getTopInventory.invoke(openInventory);
|
||||
Object type = method$InventoryView$getType.invoke(topInventory);
|
||||
isPlayerInv = type == InventoryType.CRAFTING;
|
||||
} else {
|
||||
convertSlot = player.getOpenInventory().convertSlot(slot);
|
||||
isPlayerInv = player.getOpenInventory().getTopInventory().getType() == InventoryType.CRAFTING;
|
||||
}
|
||||
|
||||
if (!(convertSlot == player.getInventory().getHeldItemSlot() || (isPlayerInv && (slot == 45 || (slot >= 5 && slot <= 8)))))
|
||||
return;
|
||||
int containerId = (int) NetworkReflections.method$ClientboundContainerSetSlotPacket$getContainerId.invoke(packet);
|
||||
int stateId = (int) NetworkReflections.method$ClientboundContainerSetSlotPacket$getStateId.invoke(packet);
|
||||
Object replacePacket = NetworkReflections.constructor$ClientboundContainerSetSlotPacket.newInstance(containerId, stateId, slot, MItems.AIR$Item);
|
||||
event.replacePacket(replacePacket);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handleContainerSetSlotPacket", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(Player player, Object event) {
|
||||
if (event instanceof PlayerAnimationEvent e) {
|
||||
try {
|
||||
Object animatePacket;
|
||||
if (e.getAnimationType() == PlayerAnimationType.ARM_SWING) {
|
||||
animatePacket = npcLeftAnimatePacket;
|
||||
} else {
|
||||
animatePacket = npcRightAnimatePacket;
|
||||
}
|
||||
serverPlayer.sendPacket(animatePacket, true);
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(animatePacket, true);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle PlayerAnimationEvent", exception);
|
||||
}
|
||||
} else if (event instanceof PlayerItemHeldEvent e) {
|
||||
ItemStack item = e.getPlayer().getInventory().getItem(e.getNewSlot());
|
||||
if (item == null) item = ItemUtils.AIR;
|
||||
|
||||
equipmentChange(Map.of(EquipmentSlot.MAIN_HAND, item), e.getPreviousSlot());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return SeatType.LAY;
|
||||
}
|
||||
|
||||
private class PlayerMonitorTask implements Runnable {
|
||||
|
||||
private final SchedulerTask task;
|
||||
private float lastYaw;
|
||||
|
||||
private PlayerMonitorTask() {
|
||||
org.bukkit.entity.Player p = serverPlayer.platformPlayer();
|
||||
BukkitCraftEngine plugin = BukkitCraftEngine.instance();
|
||||
if (VersionHelper.isFolia()) {
|
||||
this.task = new FoliaTask(p.getScheduler().runAtFixedRate(plugin.javaPlugin(), (t) -> this.run(), () -> {
|
||||
}, 1, 1));
|
||||
} else {
|
||||
this.task = plugin.scheduler().sync().runRepeating(this, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
org.bukkit.entity.Player player = serverPlayer.platformPlayer();
|
||||
if (player == null || !player.isValid()) {
|
||||
this.task.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// Invisible
|
||||
updateNpcInvisible();
|
||||
try {
|
||||
if (!player.isInvisible())
|
||||
CoreReflections.method$Entity$setInvisible.invoke(serverPlayer.serverPlayer(), true);
|
||||
} catch (Exception exception) {
|
||||
CraftEngine.instance().logger().warn("Failed to set shared flag", exception);
|
||||
}
|
||||
|
||||
// Sync Rotation
|
||||
float playerYaw = player.getYaw();
|
||||
if (lastYaw != playerYaw) {
|
||||
updateNpcYaw(playerYaw);
|
||||
serverPlayer.sendPacket(npcRotHeadPacket, false);
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(npcRotHeadPacket, true);
|
||||
}
|
||||
this.lastYaw = playerYaw;
|
||||
}
|
||||
|
||||
// Sync Equipment
|
||||
Map<EquipmentSlot, ItemStack> newEquipments = new HashMap<>();
|
||||
for (EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
if (!slot.isHand() && !slot.isPlayerArmor()) continue;
|
||||
ItemStack newItem = player.getEquipment().getItem(EntityUtils.toBukkitEquipmentSlot(slot));
|
||||
try {
|
||||
ItemStack item = equipments.get(slot);
|
||||
boolean isChange = !newItem.equals(item);
|
||||
if (isChange) {
|
||||
newEquipments.put(slot, newItem);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to monitor equipments change", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!newEquipments.isEmpty()) {
|
||||
equipmentChange(newEquipments, -1);
|
||||
return;
|
||||
}
|
||||
serverPlayer.sendPacket(emptyEquipPacket, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNpcYaw(float playerYaw) {
|
||||
byte packYaw = getRot(playerYaw);
|
||||
try {
|
||||
this.npcRotHeadPacket = NetworkReflections.constructor$ClientboundRotateHeadPacket.newInstance(npc, packYaw);
|
||||
} catch (Exception exception) {
|
||||
CraftEngine.instance().logger().warn("Failed to sync NPC yaw", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private byte getRot(float playerYaw) {
|
||||
float npcYaw = Direction.getYaw(npcDir);
|
||||
float centerYaw = normalizeYaw(npcYaw);
|
||||
float playerYawNorm = normalizeYaw(playerYaw);
|
||||
|
||||
float deltaYaw = normalizeYaw(playerYawNorm - centerYaw);
|
||||
boolean isBehind = Math.abs(deltaYaw) > 90;
|
||||
|
||||
float mappedYaw;
|
||||
if (isBehind) {
|
||||
float rel = Math.abs(deltaYaw) - 180;
|
||||
mappedYaw = rel * (deltaYaw > 0 ? -1 : 1);
|
||||
} else {
|
||||
mappedYaw = deltaYaw;
|
||||
}
|
||||
|
||||
float finalYaw = Math.max(-45, Math.min(45, mappedYaw));
|
||||
return MCUtils.packDegrees(finalYaw);
|
||||
}
|
||||
|
||||
private float normalizeYaw(float yaw) {
|
||||
yaw %= 360.0f;
|
||||
if (yaw < -180.0f) yaw += 360.0f;
|
||||
if (yaw >= 180.0f) yaw -= 360.0f;
|
||||
return yaw;
|
||||
}
|
||||
|
||||
private void updateNpcInvisible() {
|
||||
try {
|
||||
org.bukkit.entity.Player player = serverPlayer.platformPlayer();
|
||||
if (player.getPotionEffect(PotionEffectType.INVISIBILITY) == null && npcDataPacket != null) {
|
||||
npcDataPacket = null;
|
||||
CoreReflections.method$Entity$setInvisible.invoke(npc, false);
|
||||
Object npcData = CoreReflections.method$Entity$getEntityData.invoke(npc);
|
||||
Object dataItem = CoreReflections.method$SynchedEntityData$getItem.invoke(npcData, PlayerData.SharedFlags.entityDataAccessor());
|
||||
Object dataValue = CoreReflections.method$SynchedEntityData$DataItem$value.invoke(dataItem);
|
||||
Object packet = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(npcID, List.of(dataValue));
|
||||
serverPlayer.sendPacket(packet, false);
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(packet, false);
|
||||
}
|
||||
} else if (player.getPotionEffect(PotionEffectType.INVISIBILITY) != null && npcDataPacket == null) {
|
||||
CoreReflections.method$Entity$setInvisible.invoke(npc, true);
|
||||
Object npcData = CoreReflections.method$Entity$getEntityData.invoke(npc);
|
||||
Object dataItem = CoreReflections.method$SynchedEntityData$getItem.invoke(npcData, PlayerData.SharedFlags.entityDataAccessor());
|
||||
Object dataValue = CoreReflections.method$SynchedEntityData$DataItem$value.invoke(dataItem);
|
||||
npcDataPacket = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(npcID, List.of(dataValue));
|
||||
serverPlayer.sendPacket(npcDataPacket, false);
|
||||
for (NetWorkUser tracker : trackers) {
|
||||
tracker.sendPacket(npcDataPacket, false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to updateNpcInvisible", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements SeatFactory {
|
||||
|
||||
@Override
|
||||
public Seat create(List<String> args) {
|
||||
Vector3f offset = MiscUtils.getAsVector3f(args.get(0), "seats");
|
||||
Direction facing = args.size() > 1 ? parseFacing(args.get(1)) : Direction.SOUTH;
|
||||
boolean sleep = args.size() > 2 && Boolean.parseBoolean(args.get(2));
|
||||
boolean phantom = args.size() > 4 && Boolean.parseBoolean(args.get(3));
|
||||
|
||||
if (facing == Direction.NORTH || facing == Direction.SOUTH) {
|
||||
float temp = offset.x;
|
||||
offset.x = offset.z;
|
||||
offset.z = temp;
|
||||
}
|
||||
return new LaySeat(offset, facing, sleep, phantom);
|
||||
}
|
||||
|
||||
private Direction parseFacing(String facing) {
|
||||
return switch (facing.toLowerCase()) {
|
||||
case "back" -> Direction.NORTH;
|
||||
case "left" -> Direction.WEST;
|
||||
case "right" -> Direction.EAST;
|
||||
default -> Direction.SOUTH;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.seat;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SitSeat extends AbstractSeat {
|
||||
public static final SeatFactory FACTORY = new Factory();
|
||||
private final boolean limitPlayerRotation;
|
||||
|
||||
public SitSeat(Vector3f offset, float yaw, boolean limitPlayerRotation) {
|
||||
super(offset, yaw);
|
||||
this.limitPlayerRotation = limitPlayerRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeatEntity spawn(Player player, Furniture furniture) {
|
||||
return spawn((org.bukkit.entity.Player) player.platformPlayer(), furniture);
|
||||
}
|
||||
|
||||
public SeatEntity spawn(org.bukkit.entity.Player player, Furniture furniture) {
|
||||
Location location = ((BukkitFurniture) furniture).calculateSeatLocation(this);
|
||||
org.bukkit.entity.Entity seatEntity = BukkitFurniture.spawnSeatEntity(furniture, player.getWorld(), location, this.limitPlayerRotation, null);
|
||||
if (!seatEntity.addPassenger(player)) {
|
||||
seatEntity.remove();
|
||||
return null;
|
||||
}
|
||||
return new SitEntity(seatEntity, furniture, offset(), player.getEntityId());
|
||||
}
|
||||
|
||||
private static class SitEntity extends BukkitSeatEntity {
|
||||
|
||||
public SitEntity(Entity entity, Furniture furniture, Vector3f vector3f, int playerID) {
|
||||
super(entity, furniture, vector3f, playerID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return SeatType.SIT;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements SeatFactory {
|
||||
|
||||
@Override
|
||||
public Seat create(List<String> args) {
|
||||
if (args.size() == 1) return new SitSeat(MiscUtils.getAsVector3f(args.getFirst(), "seats"), 0, false);
|
||||
return new SitSeat(MiscUtils.getAsVector3f(args.getFirst(), "seats"), Float.parseFloat(args.get(1)), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,10 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.util.Cancellable;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -73,12 +76,11 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
Player player = context.getPlayer();
|
||||
CustomBlock block = optionalBlock.get();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
int maxY = context.getLevel().worldHeight().getMaxBuildHeight() - 1;
|
||||
if (player != null && context.getClickedFace() == Direction.UP && pos.y() >= maxY) {
|
||||
player.sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED));
|
||||
if (context.getClickedFace() == Direction.UP && pos.y() >= maxY) {
|
||||
context.getPlayer().sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED));
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
@@ -87,14 +89,15 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
Player player = context.getPlayer();
|
||||
BlockPos againstPos = context.getAgainstPos();
|
||||
World world = (World) context.getLevel().platformWorld();
|
||||
Location placeLocation = new Location(world, pos.x(), pos.y(), pos.z());
|
||||
Block bukkitBlock = world.getBlockAt(placeLocation);
|
||||
Block againstBlock = world.getBlockAt(againstPos.x(), againstPos.y(), againstPos.z());
|
||||
org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null;
|
||||
org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.platformPlayer();
|
||||
|
||||
if (player != null && player.isAdventureMode()) {
|
||||
if (player.isAdventureMode()) {
|
||||
Object againstBlockState = BlockStateUtils.blockDataToBlockState(againstBlock.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(againstBlockState);
|
||||
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
@@ -110,20 +113,17 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
// trigger event
|
||||
CustomBlockAttemptPlaceEvent attemptPlaceEvent = new CustomBlockAttemptPlaceEvent(bukkitPlayer, placeLocation.clone(), blockStateToPlace,
|
||||
DirectionUtils.toBlockFace(context.getClickedFace()), bukkitBlock, context.getHand());
|
||||
if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// it's just world + pos
|
||||
BlockState previousState = bukkitBlock.getState();
|
||||
// place custom block
|
||||
CraftEngineBlocks.place(placeLocation, blockStateToPlace, UpdateOption.UPDATE_ALL_IMMEDIATE, false);
|
||||
if (player != null) {
|
||||
// call bukkit event
|
||||
BlockPlaceEvent bukkitPlaceEvent = new BlockPlaceEvent(bukkitBlock, previousState, againstBlock, (ItemStack) context.getItem().getItem(), bukkitPlayer, true, context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND);
|
||||
if (EventUtils.fireAndCheckCancel(bukkitPlaceEvent)) {
|
||||
@@ -139,7 +139,6 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
previousState.update(true, false);
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPosition position = new WorldPosition(context.getLevel(), pos.x() + 0.5, pos.y() + 0.5, pos.z() + 0.5);
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
@@ -155,7 +154,7 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
}
|
||||
|
||||
if (player != null && !player.isCreativeMode()) {
|
||||
if (!player.isCreativeMode()) {
|
||||
Item<?> item = context.getItem();
|
||||
item.count(item.count() - 1);
|
||||
item.load();
|
||||
@@ -163,9 +162,7 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
|
||||
block.setPlacedBy(context, blockStateToPlace);
|
||||
|
||||
if (player != null) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
context.getLevel().playBlockSound(position, blockStateToPlace.sounds().placeSound());
|
||||
world.sendGameEvent(bukkitPlayer, GameEvent.BLOCK_PLACE, new Vector(pos.x(), pos.y(), pos.z()));
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -182,27 +179,16 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
|
||||
protected boolean canPlace(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
try {
|
||||
Player cePlayer = context.getPlayer();
|
||||
Object player = cePlayer != null ? cePlayer.serverPlayer() : null;
|
||||
Object player = context.getPlayer().serverPlayer();
|
||||
Object blockState = state.customBlockState().handle();
|
||||
Object blockPos = LocationUtils.toBlockPos(context.getClickedPos());
|
||||
Object voxelShape;
|
||||
if (VersionHelper.isOrAbove1_21_6()) {
|
||||
voxelShape = CoreReflections.method$CollisionContext$placementContext.invoke(null, player);
|
||||
} else if (player != null) {
|
||||
voxelShape = CoreReflections.method$CollisionContext$of.invoke(null, player);
|
||||
} else {
|
||||
voxelShape = CoreReflections.instance$CollisionContext$empty;
|
||||
}
|
||||
Object voxelShape = CoreReflections.method$CollisionContext$of.invoke(null, player);
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel((World) context.getLevel().platformWorld());
|
||||
boolean defaultReturn = ((!this.checkStatePlacement() || (boolean) CoreReflections.method$BlockStateBase$canSurvive.invoke(blockState, world, blockPos))
|
||||
&& (boolean) CoreReflections.method$ServerLevel$checkEntityCollision.invoke(world, blockState, player, voxelShape, blockPos, true));
|
||||
Block block = FastNMS.INSTANCE.method$CraftBlock$at(world, blockPos);
|
||||
BlockData blockData = FastNMS.INSTANCE.method$CraftBlockData$fromData(blockState);
|
||||
BlockCanBuildEvent canBuildEvent = new BlockCanBuildEvent(
|
||||
block, cePlayer != null ? (org.bukkit.entity.Player) cePlayer.platformPlayer() : null, blockData, defaultReturn,
|
||||
context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND
|
||||
);
|
||||
BlockCanBuildEvent canBuildEvent = new BlockCanBuildEvent(block, (org.bukkit.entity.Player) context.getPlayer().platformPlayer(), blockData, defaultReturn, context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND);
|
||||
Bukkit.getPluginManager().callEvent(canBuildEvent);
|
||||
return canBuildEvent.isBuildable();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
|
||||
@@ -40,7 +40,7 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
case "1.21.4" -> {
|
||||
return new ComponentItemFactory1_21_4(plugin);
|
||||
}
|
||||
case "1.21.5", "1.21.6", "1.21.7", "1.22", "1.22.1" -> {
|
||||
case "1.21.5", "1.21.6", "1.22", "1.22.1" -> {
|
||||
return new ComponentItemFactory1_21_5(plugin);
|
||||
}
|
||||
default -> throw new IllegalStateException("Unsupported server version: " + plugin.serverVersion());
|
||||
|
||||
@@ -7,7 +7,6 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.seat.BukkitSeatTypes;
|
||||
import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
@@ -15,7 +14,6 @@ import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
import net.momirealms.craftengine.bukkit.loot.BukkitVanillaLootManager;
|
||||
import net.momirealms.craftengine.bukkit.pack.BukkitPackManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.agent.LevelInjector;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitSenderFactory;
|
||||
import net.momirealms.craftengine.bukkit.plugin.gui.BukkitGuiManager;
|
||||
@@ -136,12 +134,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
} catch (Exception e) {
|
||||
throw new InjectionException("Error initializing ProtectedFieldVisitor", e);
|
||||
}
|
||||
try {
|
||||
logger.info("Patching the server...");
|
||||
LevelInjector.patch();
|
||||
} catch (Exception e) {
|
||||
throw new InjectionException("Error injecting Level", e);
|
||||
}
|
||||
super.onPluginLoad();
|
||||
super.blockManager.init();
|
||||
super.networkManager = new BukkitNetworkManager(this);
|
||||
@@ -187,7 +179,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
BukkitItemBehaviors.init();
|
||||
BukkitHitBoxTypes.init();
|
||||
PacketConsumers.initEntities(RegistryUtils.currentEntityTypeRegistrySize());
|
||||
BukkitSeatTypes.init();
|
||||
super.packManager = new BukkitPackManager(this);
|
||||
super.senderFactory = new BukkitSenderFactory(this);
|
||||
super.itemManager = new BukkitItemManager(this);
|
||||
@@ -278,7 +269,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
|
||||
@Override
|
||||
public String serverVersion() {
|
||||
return VersionHelper.MINECRAFT_VERSION.versionString();
|
||||
return Bukkit.getServer().getBukkitVersion().split("-")[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.agent;
|
||||
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
||||
import net.bytebuddy.dynamic.scaffold.InstrumentedType;
|
||||
import net.bytebuddy.implementation.Implementation;
|
||||
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
|
||||
import net.bytebuddy.jar.asm.Opcodes;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class LevelInjector {
|
||||
|
||||
public static void patch() {
|
||||
Class<?> holderClass = new ByteBuddy()
|
||||
.subclass(Object.class)
|
||||
.name("net.momirealms.craftengine.bukkit.plugin.agent.LevelInjectorHolder")
|
||||
.defineField("callEventMethod", MethodHandle.class, Modifier.PUBLIC | Modifier.STATIC)
|
||||
.defineMethod("setCallEventMethod", void.class, Modifier.PUBLIC | Modifier.STATIC)
|
||||
.withParameters(MethodHandle.class)
|
||||
.intercept(new Implementation() {
|
||||
@Override
|
||||
public @NotNull InstrumentedType prepare(@NotNull InstrumentedType instrumentedType) {
|
||||
return instrumentedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ByteCodeAppender appender(@NotNull Target implementationTarget) {
|
||||
return (methodVisitor, implementationContext, instrumentedMethod) -> {
|
||||
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
methodVisitor.visitFieldInsn(Opcodes.PUTSTATIC,
|
||||
"net/momirealms/craftengine/bukkit/plugin/agent/LevelInjectorHolder",
|
||||
"callEventMethod",
|
||||
"Ljava/lang/invoke/MethodHandle;");
|
||||
methodVisitor.visitInsn(Opcodes.RETURN);
|
||||
return new ByteCodeAppender.Size(1, 1);
|
||||
};
|
||||
}
|
||||
})
|
||||
.make()
|
||||
.load(Bukkit.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
|
||||
.getLoaded();
|
||||
try {
|
||||
Method setCallEventMethod = holderClass.getMethod("setCallEventMethod", MethodHandle.class);
|
||||
Method callEvent = LevelInjector.class.getMethod("callEvent", Object.class, Object[].class);
|
||||
MethodHandle callEventMethod = MethodHandles.lookup().unreflect(callEvent)
|
||||
.asType(MethodType.methodType(void.class, Object.class, Object[].class));
|
||||
setCallEventMethod.invoke(null, callEventMethod);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
new AgentBuilder.Default()
|
||||
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
|
||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
||||
.type(ElementMatchers.is(CoreReflections.clazz$Level))
|
||||
.transform((builder, typeDescription, classLoader, module, protectionDomain) ->
|
||||
builder.visit(Advice.to(CallEventAdvice.class)
|
||||
.on(ElementMatchers.is(CoreReflections.method$Level$destroyBlock))))
|
||||
.installOn(ByteBuddyAgent.install());
|
||||
}
|
||||
|
||||
public static class CallEventAdvice {
|
||||
|
||||
@Advice.OnMethodEnter
|
||||
public static void onEnter(@Advice.This Object level, @Advice.AllArguments Object[] args) {
|
||||
try {
|
||||
Class<?> holder = Class.forName("net.momirealms.craftengine.bukkit.plugin.agent.LevelInjectorHolder");
|
||||
MethodHandle destroyBlockEventMethod = (MethodHandle) holder.getField("callEventMethod").get(null);
|
||||
destroyBlockEventMethod.invokeExact(level, args);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void callEvent(Object level, Object[] args) {
|
||||
Object pos = args[0];
|
||||
boolean dropBlock = (boolean) args[1];
|
||||
if (!dropBlock) return;
|
||||
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, pos);
|
||||
int stateId = BlockStateUtils.blockStateToId(state);
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (blockState == null || blockState.isEmpty()) return;
|
||||
BlockPos blockPos = LocationUtils.fromBlockPos(pos);
|
||||
for (Property<?> property : blockState.getProperties()) {
|
||||
if (property.valueClass() == DoubleBlockHalf.class) return; // 退退退不处理了气死我了
|
||||
}
|
||||
org.bukkit.World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
World world = BukkitWorldManager.instance().wrap(bukkitWorld);
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(blockPos));
|
||||
Block block = bukkitWorld.getBlockAt(blockPos.x(), blockPos.y(), blockPos.z());
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position)
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block));
|
||||
for (Item<Object> item : blockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
world.playBlockSound(position, blockState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, pos, stateId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,8 +130,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
Channel channel = future.channel();
|
||||
injectServerChannel(channel);
|
||||
this.injectedChannels.add(channel);
|
||||
}, (object) -> {
|
||||
});
|
||||
}, (object) -> {});
|
||||
CoreReflections.field$ServerConnectionListener$channels.set(serverConnection, monitor);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to init server connection", e);
|
||||
@@ -163,8 +162,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$Pos);
|
||||
registerNMSPacketConsumer(PacketConsumers.ROTATE_HEAD, NetworkReflections.clazz$ClientboundRotateHeadPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_MOTION, NetworkReflections.clazz$ClientboundSetEntityMotionPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SET_CONTAINER_SLOT, NetworkReflections.clazz$ClientboundContainerSetSlotPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.CLIENT_INFO, NetworkReflections.clazz$ServerboundClientInformationPacket);
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
@@ -301,11 +298,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
|
||||
public NetWorkUser getOnlineUser(Player player) {
|
||||
return this.getOnlineUser(player.getUniqueId());
|
||||
}
|
||||
|
||||
public NetWorkUser getOnlineUser(UUID uuid) {
|
||||
return onlineUsers.get(uuid);
|
||||
return this.onlineUsers.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public Channel getChannel(Player player) {
|
||||
|
||||
@@ -35,7 +35,6 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
@@ -181,17 +180,6 @@ public class PacketConsumers {
|
||||
user.entityPacketHandlers().put(id, FurnitureCollisionPacketHandler.INSTANCE);
|
||||
}
|
||||
};
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.PLAYER$registryId] = (user, event) -> {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
buf.readVarInt();
|
||||
UUID uuid = buf.readUUID();
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) BukkitCraftEngine.instance().networkManager().getOnlineUser(uuid);
|
||||
if (player == null) return;
|
||||
SeatEntity seat = player.seat();
|
||||
if (seat == null) return;
|
||||
user.entityPacketHandlers().put(seat.playerID(), seat);
|
||||
seat.add(user);
|
||||
};
|
||||
}
|
||||
|
||||
private static BukkitNetworkManager.Handlers simpleAddEntityHandler(EntityPacketHandler handler) {
|
||||
@@ -523,8 +511,7 @@ public class PacketConsumers {
|
||||
return;
|
||||
}
|
||||
EnumSet<? extends Enum<?>> enums = FastNMS.INSTANCE.field$ClientboundPlayerInfoUpdatePacket$actions(packet);
|
||||
outer:
|
||||
{
|
||||
outer: {
|
||||
for (Object entry : enums) {
|
||||
if (entry == NetworkReflections.instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_DISPLAY_NAME) {
|
||||
break outer;
|
||||
@@ -1130,8 +1117,7 @@ public class PacketConsumers {
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPlayerActionPacket", e);
|
||||
}
|
||||
}, () -> {
|
||||
});
|
||||
}, () -> {});
|
||||
} else {
|
||||
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
||||
}
|
||||
@@ -1304,8 +1290,7 @@ public class PacketConsumers {
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
||||
}
|
||||
}, () -> {
|
||||
});
|
||||
}, () -> {});
|
||||
} else {
|
||||
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
||||
}
|
||||
@@ -1443,8 +1428,7 @@ public class PacketConsumers {
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
||||
}
|
||||
}, () -> {
|
||||
});
|
||||
}, () -> {});
|
||||
} else {
|
||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
||||
try {
|
||||
@@ -1515,7 +1499,7 @@ public class PacketConsumers {
|
||||
for (int i = 0, size = intList.size(); i < size; i++) {
|
||||
int entityId = intList.getInt(i);
|
||||
EntityPacketHandler handler = user.entityPacketHandlers().remove(entityId);
|
||||
if (handler != null && handler.handleEntitiesRemove(user, intList)) {
|
||||
if (handler != null && handler.handleEntitiesRemove(intList)) {
|
||||
isChange = true;
|
||||
}
|
||||
}
|
||||
@@ -1665,8 +1649,6 @@ public class PacketConsumers {
|
||||
if (!serverPlayer.isSecondaryUseActive()) {
|
||||
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
||||
if (furniture.tryOccupySeat(seatPos)) {
|
||||
SeatEntity currentSeat = serverPlayer.seat();
|
||||
if (currentSeat != null) currentSeat.dismount(serverPlayer);
|
||||
furniture.spawnSeatEntityForPlayer(serverPlayer, seatPos);
|
||||
}
|
||||
});
|
||||
@@ -1691,8 +1673,7 @@ public class PacketConsumers {
|
||||
}
|
||||
|
||||
if (VersionHelper.isFolia()) {
|
||||
platformPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> mainThreadTask.run(), () -> {
|
||||
});
|
||||
platformPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> mainThreadTask.run(), () -> {});
|
||||
} else {
|
||||
BukkitCraftEngine.instance().scheduler().executeSync(mainThreadTask);
|
||||
}
|
||||
@@ -1934,10 +1915,6 @@ public class PacketConsumers {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> SET_ENTITY_DATA = (user, event) -> {
|
||||
try {
|
||||
SeatEntity seat = ((BukkitServerPlayer) user).seat();
|
||||
if (seat != null) {
|
||||
seat.handleSetEntityData(user, event);
|
||||
}
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
EntityPacketHandler handler = user.entityPacketHandlers().get(id);
|
||||
@@ -2202,10 +2179,6 @@ public class PacketConsumers {
|
||||
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, pair.getSecond());
|
||||
}
|
||||
}
|
||||
EntityPacketHandler handler = user.entityPacketHandlers().get(entity);
|
||||
if (handler != null) {
|
||||
handler.handleSetEquipment(user, event, slots);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEquipmentPacket", e);
|
||||
}
|
||||
@@ -2443,32 +2416,4 @@ public class PacketConsumers {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityMotionPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SET_CONTAINER_SLOT = (user, event, packet) -> {
|
||||
try {
|
||||
SeatEntity seat = ((BukkitServerPlayer) user).seat();
|
||||
if (seat != null) seat.handleContainerSetSlot(user, event, packet);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEquipmentPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CLIENT_INFO = (user, event, packet) -> {
|
||||
try {
|
||||
Map<String, Object> information = FastNMS.INSTANCE.method$ServerboundClientInformationPacket$information(packet);
|
||||
user.setClientInformation(new ClientInformation(
|
||||
(String) information.getOrDefault("language", "en_us"),
|
||||
(int) information.getOrDefault("viewDistance", 2),
|
||||
information.getOrDefault("chatVisibility", null),
|
||||
(boolean) information.getOrDefault("chatColors", true),
|
||||
(int) information.getOrDefault("modelCustomisation", 0),
|
||||
information.getOrDefault("mainHand", null),
|
||||
(boolean) information.getOrDefault("textFilteringEnabled", false),
|
||||
(boolean) information.getOrDefault("allowsListing", false),
|
||||
information.getOrDefault("particleStatus", null)
|
||||
));
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundClientInformationPacket", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class FurniturePacketHandler implements EntityPacketHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleEntitiesRemove(NetWorkUser user, IntList entityIds) {
|
||||
public boolean handleEntitiesRemove(IntList entityIds) {
|
||||
entityIds.addAll(this.fakeEntities);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import com.google.common.collect.ForwardingMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.serialization.Codec;
|
||||
@@ -3504,243 +3503,4 @@ public final class CoreReflections {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Entity$setInvisible = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Entity, new String[]{"j", "setInvisible"}, boolean.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$GameProfile = requireNonNull(
|
||||
ReflectionUtils.getClazz("com.mojang.authlib.GameProfile")
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$GameProfile = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$GameProfile, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$GameProfile$getProperties = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$GameProfile, ForwardingMultimap.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ServerPlayer = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$ServerPlayer, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ServerPlayer$getGameProfile = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ServerPlayer, clazz$GameProfile, 0
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20.2 +
|
||||
public static final Method method$ServerPlayer$clientInformation = Optional.ofNullable(clazz$ClientInformation)
|
||||
.map(it -> ReflectionUtils.getMethod(clazz$ServerPlayer, it, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Class<?> clazz$CompoundTag = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"nbt.NBTTagCompound",
|
||||
"nbt.CompoundTag"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$CompoundTag$Empty;
|
||||
|
||||
static {
|
||||
try {
|
||||
instance$CompoundTag$Empty = CoreReflections.clazz$CompoundTag.getConstructor().newInstance();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to instantiate empty CompoundTag", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Entity$getEntityData = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Entity, clazz$SynchedEntityData, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$SynchedEntityData$set = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$SynchedEntityData, void.class, clazz$EntityDataAccessor, Object.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$SynchedEntityData$isDirty = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$SynchedEntityData, boolean.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$SynchedEntityData$packDirty = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$SynchedEntityData, List.class, new String[]{"b", "packDirty"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$SynchedEntityData$DataItem = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.syncher.DataWatcher$Item",
|
||||
"network.syncher.SynchedEntityData$DataItem"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$SynchedEntityData$getItem = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$SynchedEntityData, clazz$SynchedEntityData$DataItem, clazz$EntityDataAccessor)
|
||||
);
|
||||
|
||||
public static final Method method$SynchedEntityData$DataItem$value = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$SynchedEntityData$DataItem, clazz$SynchedEntityData$DataValue, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$RemoteChatSession$Data = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.chat.RemoteChatSession$a",
|
||||
"network.chat.RemoteChatSession$Data"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$GameType$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$GameType, clazz$GameType.arrayType()
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$GameType$SURVIVAL;
|
||||
public static final Object instance$GameType$CREATIVE;
|
||||
public static final Object instance$GameType$ADVENTURE;
|
||||
public static final Object instance$GameType$SPECTATOR;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$GameType$values.invoke(null);
|
||||
instance$GameType$SURVIVAL = values[0];
|
||||
instance$GameType$CREATIVE = values[1];
|
||||
instance$GameType$ADVENTURE = values[2];
|
||||
instance$GameType$SPECTATOR = values[3];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 1.21.3 +
|
||||
public static final Class<?> clazz$PositionMoveRotation = ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation")
|
||||
);
|
||||
|
||||
public static final Method method$PositionMoveRotation$of = Optional.ofNullable(clazz$PositionMoveRotation)
|
||||
.map(it -> ReflectionUtils.getStaticMethod(it, it, clazz$Entity))
|
||||
.orElse(null);
|
||||
|
||||
public static final Method method$Entity$absSnapTo = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Entity, void.class, double.class, double.class, double.class, float.class, float.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Entity$setSharedFlag = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$Entity, void.class, int.class, boolean.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Level$destroyBlock = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$Level, boolean.class, clazz$BlockPos, boolean.class, clazz$Entity, int.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$TickPriority = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.ticks.TickListPriority",
|
||||
"world.ticks.TickPriority"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$TickPriority$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(clazz$TickPriority, clazz$TickPriority.arrayType())
|
||||
);
|
||||
|
||||
public static final Object instance$TickPriority$EXTREMELY_HIGH;
|
||||
public static final Object instance$TickPriority$VERY_HIGH;
|
||||
public static final Object instance$TickPriority$HIGH;
|
||||
public static final Object instance$TickPriority$NORMAL;
|
||||
public static final Object instance$TickPriority$LOW;
|
||||
public static final Object instance$TickPriority$VERY_LOW;
|
||||
public static final Object instance$TickPriority$EXTREMELY_LOW;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$TickPriority$values.invoke(null);
|
||||
instance$TickPriority$EXTREMELY_HIGH = values[0];
|
||||
instance$TickPriority$VERY_HIGH = values[1];
|
||||
instance$TickPriority$HIGH = values[2];
|
||||
instance$TickPriority$NORMAL = values[3];
|
||||
instance$TickPriority$LOW = values[4];
|
||||
instance$TickPriority$VERY_LOW = values[5];
|
||||
instance$TickPriority$EXTREMELY_LOW = values[6];
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$WorldlyContainerHolder = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.IInventoryHolder",
|
||||
"world.WorldlyContainerHolder"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ChestBlockEntity = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.block.entity.TileEntityChest",
|
||||
"world.level.block.entity.ChestBlockEntity"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ChestBlock = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.block.BlockChest",
|
||||
"world.level.block.ChestBlock"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ItemEntity = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.entity.item.EntityItem",
|
||||
"world.entity.item.ItemEntity"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$BlockItem = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.ItemBlock",
|
||||
"world.item.BlockItem"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$CollisionContext$empty;
|
||||
|
||||
static {
|
||||
try {
|
||||
instance$CollisionContext$empty = requireNonNull(method$CollisionContext$empty.invoke(null));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 1.21.6+
|
||||
public static final Method method$CollisionContext$placementContext = ReflectionUtils.getStaticMethod(
|
||||
clazz$CollisionContext, clazz$CollisionContext, clazz$Player
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
|
||||
public final class MItems {
|
||||
private MItems() {}
|
||||
@@ -23,6 +22,4 @@ public final class MItems {
|
||||
throw new ReflectionInitException("Failed to init Items", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Object AIR$Item = FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(ItemUtils.AIR);
|
||||
}
|
||||
|
||||
@@ -178,10 +178,6 @@ public final class NetworkReflections {
|
||||
"network.protocol.game.ClientboundAddPlayerPacket"
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundAddPlayerPacket = Optional.ofNullable(clazz$ClientboundAddPlayerPacket)
|
||||
.map(it -> ReflectionUtils.getConstructor(clazz$ClientboundAddPlayerPacket, CoreReflections.clazz$Player))
|
||||
.orElse(null);
|
||||
|
||||
public static final Class<?> clazz$ClientboundRemoveEntitiesPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.PacketPlayOutEntityDestroy",
|
||||
@@ -386,30 +382,12 @@ public final class NetworkReflections {
|
||||
ReflectionUtils.getStaticMethod(clazz$ClientboundPlayerInfoUpdatePacket$Action, clazz$ClientboundPlayerInfoUpdatePacket$Action.arrayType())
|
||||
);
|
||||
|
||||
|
||||
public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$ADD_PLAYER;
|
||||
public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$INITIALIZE_CHAT;
|
||||
public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_GAME_MODE;
|
||||
public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_LISTED;
|
||||
public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_LATENCY;
|
||||
public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_DISPLAY_NAME;
|
||||
//public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_LIST_ORDER;
|
||||
//public static final Object instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_HAT;
|
||||
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$ClientboundPlayerInfoUpdatePacket$Action$values.invoke(null);
|
||||
instance$ClientboundPlayerInfoUpdatePacket$Action$ADD_PLAYER = values[0];
|
||||
instance$ClientboundPlayerInfoUpdatePacket$Action$INITIALIZE_CHAT = values[1];
|
||||
instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_GAME_MODE = values[2];
|
||||
instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_LISTED = values[3];
|
||||
instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_LATENCY = values[4];
|
||||
instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_DISPLAY_NAME = values[5];
|
||||
//1.21.3
|
||||
//instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_LIST_ORDER = values[6];
|
||||
//1.21.4
|
||||
//instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_HAT = values[7];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -1111,12 +1089,20 @@ public final class NetworkReflections {
|
||||
ReflectionUtils.getDeclaredConstructor(clazz$ClientboundMoveEntityPacket$Pos, int.class, short.class, short.class, short.class, boolean.class)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundClientInformationPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
List.of("network.protocol.game.PacketPlayInSettings", "network.protocol.common.ServerboundClientInformationPacket"),
|
||||
List.of("network.protocol.game.ServerboundClientInformationPacket", "network.protocol.common.ServerboundClientInformationPacket")
|
||||
)
|
||||
);
|
||||
// 1.20.2+
|
||||
public static final Class<?> clazz$ServerboundClientInformationPacket =
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundClientInformationPacket"));
|
||||
|
||||
// 1.20.2+
|
||||
public static final Constructor<?> constructor$ServerboundClientInformationPacket = Optional.ofNullable(clazz$ServerboundClientInformationPacket)
|
||||
.map(it -> ReflectionUtils.getConstructor(it, 1))
|
||||
.orElse(null);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Field field$ServerboundClientInformationPacket$information = Optional.ofNullable(clazz$ServerboundClientInformationPacket)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, 0))
|
||||
.orElse(null);
|
||||
|
||||
|
||||
public static final Class<?> clazz$ClientboundSetTitleTextPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
@@ -1498,78 +1484,4 @@ public final class NetworkReflections {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final Class<?> clazz$ClientBoundPlayerInfoUpdatePacket$Entry = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.ClientboundPlayerInfoUpdatePacket$b",
|
||||
"network.protocol.game.ClientboundPlayerInfoUpdatePacket$Entry"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientBoundPlayerInfoUpdatePacket$Entry = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_3()
|
||||
? VersionHelper.isOrAbove1_21_4()
|
||||
? ReflectionUtils.getConstructor(clazz$ClientBoundPlayerInfoUpdatePacket$Entry, UUID.class, CoreReflections.clazz$GameProfile, boolean.class, int.class, CoreReflections.clazz$GameType, CoreReflections.clazz$Component, boolean.class, int.class, CoreReflections.clazz$RemoteChatSession$Data)
|
||||
: ReflectionUtils.getConstructor(clazz$ClientBoundPlayerInfoUpdatePacket$Entry, UUID.class, CoreReflections.clazz$GameProfile, boolean.class, int.class, CoreReflections.clazz$GameType, CoreReflections.clazz$Component, int.class, CoreReflections.clazz$RemoteChatSession$Data)
|
||||
: ReflectionUtils.getConstructor(clazz$ClientBoundPlayerInfoUpdatePacket$Entry, UUID.class, CoreReflections.clazz$GameProfile, boolean.class, int.class, CoreReflections.clazz$GameType, CoreReflections.clazz$Component, CoreReflections.clazz$RemoteChatSession$Data)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundTeleportEntityPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.PacketPlayOutEntityTeleport",
|
||||
"network.protocol.game.ClientboundTeleportEntityPacket"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundTeleportEntityPacket = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_3()
|
||||
? ReflectionUtils.getConstructor(clazz$ClientboundTeleportEntityPacket, int.class, CoreReflections.clazz$PositionMoveRotation, Set.class, boolean.class)
|
||||
: ReflectionUtils.getConstructor(clazz$ClientboundTeleportEntityPacket, CoreReflections.clazz$Entity)
|
||||
);
|
||||
|
||||
public static final Method method$ClientboundSetEquipmentPacket$getEntity = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
NetworkReflections.clazz$ClientboundSetEquipmentPacket, int.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ClientboundSetEquipmentPacket$getSlots = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
NetworkReflections.clazz$ClientboundSetEquipmentPacket, List.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ClientboundContainerSetSlotPacket$getContainerId = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ClientboundContainerSetSlotPacket, int.class, new String[]{"a", "getContainerId"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ClientboundContainerSetSlotPacket$getSlot = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ClientboundContainerSetSlotPacket, int.class, new String[]{"c", "d", "getSlot"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ClientboundContainerSetSlotPacket$getStateId = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ClientboundContainerSetSlotPacket, int.class, new String[]{"e", "f", "getStateId"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundAnimatePacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.PacketPlayOutAnimation",
|
||||
"network.protocol.game.ClientboundAnimatePacket")
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundAnimatePacket = requireNonNull(
|
||||
ReflectionUtils.getConstructor(clazz$ClientboundAnimatePacket, CoreReflections.clazz$Entity, int.class)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundRotateHeadPacket = requireNonNull(
|
||||
ReflectionUtils.getDeclaredConstructor(
|
||||
clazz$ClientboundRotateHeadPacket, CoreReflections.clazz$Entity, byte.class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.GameMode;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
@@ -32,7 +31,6 @@ import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
|
||||
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||
import net.momirealms.craftengine.core.util.ClientInformation;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -77,7 +75,6 @@ public class BukkitServerPlayer extends Player {
|
||||
// client side dimension info
|
||||
private int sectionCount;
|
||||
private Key clientSideDimension;
|
||||
private ClientInformation clientInformation;
|
||||
// check main hand/offhand interaction
|
||||
private int lastSuccessfulInteraction;
|
||||
// re-sync attribute timely to prevent some bugs
|
||||
@@ -111,8 +108,6 @@ public class BukkitServerPlayer extends Player {
|
||||
private double cachedInteractionRange;
|
||||
// cooldown data
|
||||
private CooldownData cooldownData;
|
||||
// cache seat
|
||||
private SeatEntity seatEntity;
|
||||
|
||||
private final Map<Integer, EntityPacketHandler> entityTypeView = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -889,16 +884,6 @@ public class BukkitServerPlayer extends Player {
|
||||
this.sentResourcePack = sentResourcePack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientInformation(ClientInformation clientInformation) {
|
||||
this.clientInformation = clientInformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientInformation clientInformation() {
|
||||
return this.clientInformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView() {
|
||||
this.entityTypeView.clear();
|
||||
@@ -979,14 +964,4 @@ public class BukkitServerPlayer extends Player {
|
||||
public CooldownData cooldown() {
|
||||
return this.cooldownData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeat(SeatEntity seatEntity) {
|
||||
this.seatEntity = seatEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeatEntity seat() {
|
||||
return this.seatEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.entity.EquipmentSlot;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.Location;
|
||||
@@ -14,9 +13,6 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static net.momirealms.craftengine.core.entity.EquipmentSlot.BODY;
|
||||
import static net.momirealms.craftengine.core.entity.EquipmentSlot.MAIN_HAND;
|
||||
|
||||
public class EntityUtils {
|
||||
|
||||
private EntityUtils() {}
|
||||
@@ -38,41 +34,4 @@ public class EntityUtils {
|
||||
return LegacyEntityUtils.spawnEntity(world, loc, type, function);
|
||||
}
|
||||
}
|
||||
|
||||
public static org.bukkit.inventory.EquipmentSlot toBukkitEquipmentSlot(EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case MAIN_HAND -> org.bukkit.inventory.EquipmentSlot.HAND;
|
||||
case OFF_HAND -> org.bukkit.inventory.EquipmentSlot.OFF_HAND;
|
||||
case HEAD -> org.bukkit.inventory.EquipmentSlot.HEAD;
|
||||
case CHEST -> org.bukkit.inventory.EquipmentSlot.CHEST;
|
||||
case LEGS -> org.bukkit.inventory.EquipmentSlot.LEGS;
|
||||
case FEET -> org.bukkit.inventory.EquipmentSlot.FEET;
|
||||
default -> org.bukkit.inventory.EquipmentSlot.BODY;
|
||||
};
|
||||
}
|
||||
|
||||
public static EquipmentSlot toCEEquipmentSlot(org.bukkit.inventory.EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case HAND -> MAIN_HAND;
|
||||
case OFF_HAND -> EquipmentSlot.OFF_HAND;
|
||||
case HEAD -> EquipmentSlot.HEAD;
|
||||
case CHEST -> EquipmentSlot.CHEST;
|
||||
case LEGS -> EquipmentSlot.LEGS;
|
||||
case FEET -> EquipmentSlot.FEET;
|
||||
case BODY -> EquipmentSlot.BODY;
|
||||
default -> BODY;
|
||||
};
|
||||
}
|
||||
|
||||
public static Object fromEquipmentSlot(EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case MAIN_HAND -> CoreReflections.instance$EquipmentSlot$MAINHAND;
|
||||
case OFF_HAND -> CoreReflections.instance$EquipmentSlot$OFFHAND;
|
||||
case HEAD -> CoreReflections.instance$EquipmentSlot$HEAD;
|
||||
case CHEST -> CoreReflections.instance$EquipmentSlot$CHEST;
|
||||
case LEGS -> CoreReflections.instance$EquipmentSlot$LEGS;
|
||||
case FEET -> CoreReflections.instance$EquipmentSlot$FEET;
|
||||
default -> new Object();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import org.jetbrains.annotations.Contract;
|
||||
|
||||
public class ItemUtils {
|
||||
|
||||
public static final ItemStack AIR = new ItemStack(Material.AIR);
|
||||
|
||||
private ItemUtils() {}
|
||||
|
||||
@Contract("null -> true")
|
||||
|
||||
@@ -8,7 +8,6 @@ import net.momirealms.craftengine.bukkit.plugin.network.BukkitNetworkManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -21,7 +20,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -176,8 +174,4 @@ public final class PlayerUtils {
|
||||
BukkitCraftEngine.instance().logger().warn("Failed to send totem animation");
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<Player> getTrackedBy(Player player) {
|
||||
return VersionHelper.isOrAbove1_20_2() ? player.getTrackedBy() : player.getTrackedPlayers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,8 +235,6 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
public <T> net.momirealms.craftengine.core.world.World wrap(T world) {
|
||||
if (world instanceof World w) {
|
||||
return new BukkitWorld(w);
|
||||
} else if (CoreReflections.clazz$Level.isInstance(world)) {
|
||||
return new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(world));
|
||||
} else {
|
||||
throw new IllegalArgumentException(world.getClass() + " is not a Bukkit World");
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ resource-pack:
|
||||
- "@vanilla_textures"
|
||||
bypass-models:
|
||||
- "@vanilla_models"
|
||||
- "minecraft:item/player_head"
|
||||
bypass-sounds: []
|
||||
bypass-equipments: []
|
||||
# Validate if there are any errors in the resource pack, such as missing textures or models
|
||||
|
||||
@@ -3932,6 +3932,8 @@ minecraft:petrified_oak_slab[type=double,waterlogged=false]: minecraft:oak_slab[
|
||||
minecraft:petrified_oak_slab[type=bottom,waterlogged=true]: minecraft:oak_slab[type=bottom,waterlogged=true]
|
||||
minecraft:petrified_oak_slab[type=top,waterlogged=true]: minecraft:oak_slab[type=top,waterlogged=true]
|
||||
minecraft:petrified_oak_slab[type=double,waterlogged=true]: minecraft:oak_slab[type=double,waterlogged=true]
|
||||
|
||||
$$>=1.20.3#slab:
|
||||
minecraft:cut_copper_slab[type=bottom,waterlogged=false]: minecraft:waxed_cut_copper_slab[type=bottom,waterlogged=false]
|
||||
minecraft:cut_copper_slab[type=top,waterlogged=false]: minecraft:waxed_cut_copper_slab[type=top,waterlogged=false]
|
||||
minecraft:cut_copper_slab[type=double,waterlogged=false]: minecraft:waxed_cut_copper_slab[type=double,waterlogged=false]
|
||||
@@ -3958,6 +3960,7 @@ minecraft:oxidized_cut_copper_slab[type=top,waterlogged=true]: minecraft:waxed_o
|
||||
minecraft:oxidized_cut_copper_slab[type=double,waterlogged=true]: minecraft:waxed_oxidized_cut_copper_slab[type=double,waterlogged=true]
|
||||
|
||||
#### Stairs ####
|
||||
$$>=1.20.3#stairs:
|
||||
minecraft:cut_copper_stairs[facing=east,half=bottom,shape=straight,waterlogged=false]: minecraft:waxed_cut_copper_stairs[facing=east,half=bottom,shape=straight,waterlogged=false]
|
||||
minecraft:cut_copper_stairs[facing=east,half=bottom,shape=straight,waterlogged=true]: minecraft:waxed_cut_copper_stairs[facing=east,half=bottom,shape=straight,waterlogged=true]
|
||||
minecraft:cut_copper_stairs[facing=east,half=bottom,shape=inner_left,waterlogged=false]: minecraft:waxed_cut_copper_stairs[facing=east,half=bottom,shape=inner_left,waterlogged=false]
|
||||
|
||||
@@ -515,6 +515,7 @@ items:
|
||||
parent: minecraft:block/slab_top
|
||||
textures: *textures
|
||||
model_double_path: minecraft:block/custom/palm_planks
|
||||
$$>=1.20.3#palm_stairs:
|
||||
default:palm_stairs:
|
||||
material: nether_brick
|
||||
custom-model-data: 1013
|
||||
|
||||
@@ -152,7 +152,6 @@ warning.config.furniture.element.missing_item: "<yellow>Issue found in file <arg
|
||||
warning.config.furniture.settings.unknown: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using an unknown setting type '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using an invalid hitbox type '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using a custom hitbox with invalid entity type '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.seat.invalid_type: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using an invalid seat type '<arg:2>'.</yellow>"
|
||||
warning.config.item.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated item '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||
warning.config.item.settings.unknown: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an unknown setting type '<arg:2>'.</yellow>"
|
||||
warning.config.item.settings.invulnerable.invalid_damage_source: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an unknown damage source '<arg:2>'. Allowed sources: [<arg:3>].</yellow>"
|
||||
@@ -273,10 +272,6 @@ warning.config.block.behavior.stairs.missing_facing: "<yellow>Issue found in fil
|
||||
warning.config.block.behavior.stairs.missing_half: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'half' property for 'stairs_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.stairs.missing_shape: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'shape' property for 'stairs_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.pressure_plate.missing_powered: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'powered' property for 'pressure_plate_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.pickaxe.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'pickaxe_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.pickaxe.missing_triggered: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'triggered' property for 'pickaxe_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.place_block.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'place_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.place_block.missing_triggered: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'triggered' property for 'place_block' behavior.</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid display position '<arg:2>' in 'generation.display' section. Allowed display positions: [<arg:3>]</yellow>"
|
||||
warning.config.model.generation.invalid_gui_light: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid gui-light option '<arg:2>' in 'generation' section. Allowed gui light options: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -153,7 +153,6 @@ warning.config.furniture.element.missing_item: "<yellow>在文件 <arg:0> 发现
|
||||
warning.config.furniture.settings.unknown: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 使用了未知的设置类型 '<arg:2>'</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 使用了无效的碰撞箱类型 '<arg:2>'</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 的自定义碰撞箱使用了无效的实体类型 '<arg:2>'</yellow>"
|
||||
warning.config.furniture.seat.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 使用了无效的座椅类型 '<arg:2>'</yellow>"
|
||||
warning.config.item.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的物品 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
|
||||
warning.config.item.settings.unknown: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用了未知的设置类型 '<arg:2>'</yellow>"
|
||||
warning.config.item.settings.invulnerable.invalid_damage_source: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 物品使用了未知的伤害来源类型 '<arg:2>' 允许的来源: [<arg:3>]</yellow>"
|
||||
@@ -274,10 +273,6 @@ warning.config.block.behavior.stairs.missing_facing: "<yellow>在文件 <arg:0>
|
||||
warning.config.block.behavior.stairs.missing_half: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'stairs_block' 行为缺少必需的 'half' 属性</yellow>"
|
||||
warning.config.block.behavior.stairs.missing_shape: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'stairs_block' 行为缺少必需的 'shape' 属性</yellow>"
|
||||
warning.config.block.behavior.pressure_plate.missing_powered: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'pressure_plate_block' 行为缺少必需的 'powered' 属性</yellow>"
|
||||
warning.config.block.behavior.pickaxe.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'pickaxe_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.pickaxe.missing_triggered: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'pickaxe_block' 行为缺少必需的 'triggered' 属性</yellow>"
|
||||
warning.config.block.behavior.place_block.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'place_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.place_block.missing_triggered: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'place_block' 行为缺少必需的 'triggered' 属性</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'generation' 段落缺少必需的 'parent' 参数</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 发现问题 - 无法为 '<arg:1>' 生成模型 存在多个配置尝试使用相同路径 '<arg:2>' 生成不同的 JSON 模型</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 在 'generation.display' 区域使用了无效的 display 位置类型 '<arg:2>'. 可用展示类型: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -8,13 +8,5 @@ public enum EquipmentSlot {
|
||||
BODY,
|
||||
MAIN_HAND,
|
||||
OFF_HAND,
|
||||
SADDLE;
|
||||
|
||||
public boolean isHand() {
|
||||
return this == MAIN_HAND || this == OFF_HAND;
|
||||
}
|
||||
|
||||
public boolean isPlayerArmor() {
|
||||
return this == HEAD || this == CHEST || this == LEGS || this == FEET;
|
||||
}
|
||||
SADDLE
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractSeat implements Seat {
|
||||
protected final Vector3f offset;
|
||||
protected final float yaw;
|
||||
|
||||
public AbstractSeat(Vector3f offset, float yaw) {
|
||||
this.offset = offset;
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f offset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float yaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof AbstractSeat seat)) return false;
|
||||
return Float.compare(yaw, seat.yaw()) == 0 && offset.equals(seat.offset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hash(offset);
|
||||
result = 31 * result + Float.hashCode(yaw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,11 @@ public interface HitBoxFactory {
|
||||
static Seat[] getSeats(Map<String, Object> arguments) {
|
||||
List<String> seats = (List<String>) arguments.getOrDefault("seats", List.of());
|
||||
return seats.stream()
|
||||
.map(SeatType::fromString)
|
||||
.map(arg -> {
|
||||
String[] split = arg.split(" ");
|
||||
if (split.length == 1) return new Seat(MiscUtils.getAsVector3f(split[0], "seats"), 0, false);
|
||||
return new Seat(MiscUtils.getAsVector3f(split[0], "seats"), Float.parseFloat(split[1]), true);
|
||||
})
|
||||
.toArray(Seat[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public interface Seat {
|
||||
import java.util.Objects;
|
||||
|
||||
SeatEntity spawn(Player player, Furniture furniture);
|
||||
public record Seat(Vector3f offset, float yaw, boolean limitPlayerRotation) {
|
||||
|
||||
Vector3f offset();
|
||||
|
||||
float yaw();
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Seat seat)) return false;
|
||||
return Float.compare(yaw, seat.yaw) == 0 && Objects.equals(offset, seat.offset) && limitPlayerRotation == seat.limitPlayerRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hashCode(offset);
|
||||
result = 31 * result + Float.hashCode(yaw);
|
||||
result = 31 * result + Boolean.hashCode(limitPlayerRotation);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SeatFactory {
|
||||
|
||||
Seat create(List<String> args);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SeatType {
|
||||
public static final Key SIT = Key.of("craftengine:sit");
|
||||
public static final Key LAY = Key.of("craftengine:lay");
|
||||
public static final Key CRAWL = Key.of("craftengine:crawl");
|
||||
|
||||
public static void register(Key key, SeatFactory factory) {
|
||||
Holder.Reference<SeatFactory> holder = ((WritableRegistry<SeatFactory>) BuiltInRegistries.SEAT_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.SEAT_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
public static Seat fromString(String s) {
|
||||
int lastSpaceIndex = s.lastIndexOf(' ');
|
||||
|
||||
Key type = SIT;
|
||||
SeatFactory factory;
|
||||
String numericPart;
|
||||
|
||||
if (lastSpaceIndex != -1) {
|
||||
numericPart = s.substring(lastSpaceIndex + 1);
|
||||
try {
|
||||
Float.parseFloat(numericPart);
|
||||
} catch (NumberFormatException e) {
|
||||
type = Key.withDefaultNamespace(numericPart, "craftengine");
|
||||
s = s.substring(0, lastSpaceIndex);
|
||||
lastSpaceIndex = s.lastIndexOf(' ');
|
||||
}
|
||||
}
|
||||
|
||||
List<String> split = new ArrayList<>();
|
||||
int start = 0;
|
||||
while (lastSpaceIndex != -1) {
|
||||
split.add(s.substring(start, lastSpaceIndex));
|
||||
start = lastSpaceIndex + 1;
|
||||
lastSpaceIndex = s.indexOf(' ', start);
|
||||
}
|
||||
if (start < s.length()) {
|
||||
split.add(s.substring(start));
|
||||
}
|
||||
|
||||
factory = BuiltInRegistries.SEAT_FACTORY.getValue(type);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.seat.invalid_type", type.toString());
|
||||
}
|
||||
return factory.create(split);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package net.momirealms.craftengine.core.entity.player;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.entity.AbstractEntity;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatEntity;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.CooldownData;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
@@ -141,8 +140,4 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
|
||||
public abstract void clearPotionEffects();
|
||||
|
||||
public abstract CooldownData cooldown();
|
||||
|
||||
public abstract void setSeat(SeatEntity seatEntity);
|
||||
|
||||
public abstract SeatEntity seat();
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package net.momirealms.craftengine.core.entity.seat;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public interface SeatEntity extends EntityPacketHandler {
|
||||
|
||||
void add(NetWorkUser to);
|
||||
|
||||
void dismount(Player player);
|
||||
|
||||
void onDismount(Player player);
|
||||
|
||||
void event(Player player, Object event);
|
||||
|
||||
void destroy();
|
||||
|
||||
boolean destroyed();
|
||||
|
||||
Furniture furniture();
|
||||
|
||||
Vector3f vector3f();
|
||||
|
||||
int playerID();
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockPlaceContext extends UseOnContext {
|
||||
private final BlockPos relativePos;
|
||||
protected boolean replaceClicked;
|
||||
@@ -18,7 +16,7 @@ public class BlockPlaceContext extends UseOnContext {
|
||||
this(context.getLevel(), context.getPlayer(), context.getHand(), context.getItem(), context.getHitResult());
|
||||
}
|
||||
|
||||
public BlockPlaceContext(World world, @Nullable Player player, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
|
||||
public BlockPlaceContext(World world, Player player, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
|
||||
super(world, player, hand, stack, hit);
|
||||
this.relativePos = hit.getBlockPos().relative(hit.getDirection());
|
||||
this.replaceClicked = true;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package net.momirealms.craftengine.core.item.context;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
public class PlaceBlockBlockPlaceContext extends BlockPlaceContext {
|
||||
public PlaceBlockBlockPlaceContext(World world, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
|
||||
super(world, null, hand, stack, hit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getNearestLookingDirection() {
|
||||
return this.getHitResult().getDirection();
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,8 @@ import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UseOnContext {
|
||||
@Nullable
|
||||
private final Player player;
|
||||
private final InteractionHand hand;
|
||||
private final BlockHitResult hitResult;
|
||||
@@ -26,7 +24,7 @@ public class UseOnContext {
|
||||
this(player.world(), player, hand, stack, hit);
|
||||
}
|
||||
|
||||
public UseOnContext(World world, @Nullable Player player, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
|
||||
public UseOnContext(World world, Player player, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
|
||||
this.player = player;
|
||||
this.hand = hand;
|
||||
this.hitResult = hit;
|
||||
@@ -58,7 +56,6 @@ public class UseOnContext {
|
||||
return this.itemStack;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
@@ -72,11 +69,11 @@ public class UseOnContext {
|
||||
}
|
||||
|
||||
public Direction getHorizontalDirection() {
|
||||
return this.player == null ? Direction.NORTH : this.player.getDirection();
|
||||
return this.player.getDirection();
|
||||
}
|
||||
|
||||
public boolean isSecondaryUseActive() {
|
||||
return this.player != null && this.player.isSecondaryUseActive();
|
||||
return this.player.isSecondaryUseActive();
|
||||
}
|
||||
|
||||
public float getRotation() {
|
||||
|
||||
@@ -236,6 +236,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
int fileCount = ObfA.VALUES[1] - ObfA.VALUES[17];
|
||||
Constructor<?> magicConstructor = ReflectionUtils.getConstructor(magicClazz, fileCount);
|
||||
assert magicConstructor != null;
|
||||
// magicConstructor.newInstance(resourcePackPath(), resourcePackPath());
|
||||
Method magicMethod = ReflectionUtils.getMethod(magicClazz, void.class);
|
||||
assert magicMethod != null;
|
||||
this.zipGenerator = (p1, p2) -> {
|
||||
@@ -244,7 +245,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
magicMethod.invoke(magicObject);
|
||||
} catch (ResourcePackGenerationException e) {
|
||||
this.plugin.logger().warn("Failed to generate resource pack: " + e.getMessage());
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to generate zip files\n" + new StringWriter(){{e.printStackTrace(new PrintWriter(this));}}.toString().replaceAll("\\.[Il]{2,}", "").replaceAll("/[Il]{2,}", ""));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ public interface Revision {
|
||||
@Override
|
||||
public String versionString() {
|
||||
if (this.versionString == null) {
|
||||
this.versionString = this.minVersion.versionString().replace(".", "_");
|
||||
this.versionString = this.minVersion.version().replace(".", "_");
|
||||
}
|
||||
return this.versionString;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public interface Revision {
|
||||
@Override
|
||||
public String versionString() {
|
||||
if (this.versionString == null) {
|
||||
this.versionString = this.minVersion.versionString().replace(".", "_") + "-" + this.maxVersion.versionString().replace(".", "_");
|
||||
this.versionString = this.minVersion.version().replace(".", "_") + "-" + this.maxVersion.version().replace(".", "_");
|
||||
}
|
||||
return this.versionString;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.plugin.config.template;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
|
||||
@@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.ints.IntList;
|
||||
|
||||
public interface EntityPacketHandler {
|
||||
|
||||
default boolean handleEntitiesRemove(NetWorkUser user, IntList entityIds) {
|
||||
default boolean handleEntitiesRemove(IntList entityIds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19,10 +19,4 @@ public interface EntityPacketHandler {
|
||||
|
||||
default void handleMove(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||
}
|
||||
|
||||
default void handleSetEquipment(NetWorkUser user, ByteBufPacketEvent event, Object slots) {
|
||||
}
|
||||
|
||||
default void handleContainerSetSlot(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.plugin.Plugin;
|
||||
import net.momirealms.craftengine.core.util.ClientInformation;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@@ -65,8 +64,4 @@ public interface NetWorkUser {
|
||||
boolean sentResourcePack();
|
||||
|
||||
void setSentResourcePack(boolean sentResourcePack);
|
||||
|
||||
void setClientInformation(ClientInformation clientInformation);
|
||||
|
||||
ClientInformation clientInformation();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.SeatFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
@@ -69,7 +68,6 @@ public class BuiltInRegistries {
|
||||
public static final Registry<FunctionFactory<PlayerOptionalContext>> EVENT_FUNCTION_FACTORY = createRegistry(Registries.EVENT_FUNCTION_FACTORY);
|
||||
public static final Registry<ConditionFactory<PlayerOptionalContext>> EVENT_CONDITION_FACTORY = createRegistry(Registries.EVENT_CONDITION_FACTORY);
|
||||
public static final Registry<PlayerSelectorFactory<?>> PLAYER_SELECTOR_FACTORY = createRegistry(Registries.PLAYER_SELECTOR_FACTORY);
|
||||
public static final Registry<SeatFactory> SEAT_FACTORY = createRegistry(Registries.SEAT_FACTORY);
|
||||
|
||||
private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) {
|
||||
return new MappedRegistry<>(key);
|
||||
|
||||
@@ -4,7 +4,6 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.SeatFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
@@ -70,5 +69,4 @@ public class Registries {
|
||||
public static final ResourceKey<Registry<FunctionFactory<PlayerOptionalContext>>> EVENT_FUNCTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_function_factory"));
|
||||
public static final ResourceKey<Registry<ConditionFactory<PlayerOptionalContext>>> EVENT_CONDITION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_condition_factory"));
|
||||
public static final ResourceKey<Registry<PlayerSelectorFactory<?>>> PLAYER_SELECTOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_selector"));
|
||||
public static final ResourceKey<Registry<SeatFactory>> SEAT_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("seat_factory"));
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package net.momirealms.craftengine.core.util;
|
||||
|
||||
public record ClientInformation(String language, int viewDistance, Object chatVisibility,
|
||||
boolean chatColors, int modelCustomisation, Object mainHand,
|
||||
boolean textFilteringEnabled, boolean allowsListing, Object particleStatus) {
|
||||
}
|
||||
@@ -20,7 +20,6 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
PACK_FORMATS.put(1_21_04, 46);
|
||||
PACK_FORMATS.put(1_21_05, 55);
|
||||
PACK_FORMATS.put(1_21_06, 63);
|
||||
PACK_FORMATS.put(1_21_07, 63);
|
||||
PACK_FORMATS.put(1_99_99, 1000);
|
||||
}
|
||||
|
||||
@@ -32,11 +31,7 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
return new MinecraftVersion(version);
|
||||
}
|
||||
|
||||
public int version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String versionString() {
|
||||
public String version() {
|
||||
return versionString;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,5 @@ public final class MinecraftVersions {
|
||||
public static final MinecraftVersion V1_21_4 = new MinecraftVersion("1.21.4");
|
||||
public static final MinecraftVersion V1_21_5 = new MinecraftVersion("1.21.5");
|
||||
public static final MinecraftVersion V1_21_6 = new MinecraftVersion("1.21.6");
|
||||
public static final MinecraftVersion V1_21_7 = new MinecraftVersion("1.21.7");
|
||||
public static final MinecraftVersion FUTURE = new MinecraftVersion("1.99.99");
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class SNBTReader extends DefaultStringReader {
|
||||
private static final char COMPOUND_START = '{';
|
||||
@@ -17,11 +16,6 @@ public final class SNBTReader extends DefaultStringReader {
|
||||
private static final char KEY_VALUE_SEPARATOR = ':';
|
||||
private static final char ELEMENT_SEPARATOR = ',';
|
||||
|
||||
private static final char ARRAY_DELIMITER = ';';
|
||||
private static final char BYTE_ARRAY = 'b';
|
||||
private static final char INT_ARRAY = 'i';
|
||||
private static final char LONG_ARRAY = 'l';
|
||||
|
||||
// 数字类型后缀
|
||||
private static final char BYTE_SUFFIX = 'b';
|
||||
private static final char SHORT_SUFFIX = 's';
|
||||
@@ -87,53 +81,9 @@ public final class SNBTReader extends DefaultStringReader {
|
||||
}
|
||||
|
||||
// 解析列表值 [1, 2, 3]
|
||||
private Object parseList() {
|
||||
private List<Object> parseList() {
|
||||
skip(); // 跳过 '['
|
||||
skipWhitespace();
|
||||
|
||||
// 检查接下来的2个非空格字符, 确认是否要走数组解析.
|
||||
if (canRead()) {
|
||||
setMarker(cursor); // 记录指针, 尝试解析数组.
|
||||
char typeChar = Character.toLowerCase(peek());
|
||||
if (typeChar == BYTE_ARRAY || typeChar == INT_ARRAY || typeChar == LONG_ARRAY) {
|
||||
skip();
|
||||
skipWhitespace();
|
||||
if (canRead() && peek() == ARRAY_DELIMITER) { // 下一个必须是 ';'
|
||||
skip();
|
||||
switch (typeChar) { // 解析并返回数组喵
|
||||
case BYTE_ARRAY -> {
|
||||
return parseArray(list -> {
|
||||
byte[] bytes = new byte[list.size()];
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = list.get(i).byteValue();
|
||||
}
|
||||
return bytes;
|
||||
});
|
||||
}
|
||||
case INT_ARRAY -> {
|
||||
return parseArray(list -> {
|
||||
int[] ints = new int[list.size()];
|
||||
for (int i = 0; i < ints.length; i++) {
|
||||
ints[i] = list.get(i).intValue();
|
||||
}
|
||||
return ints;
|
||||
});
|
||||
}
|
||||
case LONG_ARRAY -> {
|
||||
return parseArray(list -> {
|
||||
long[] longs = new long[list.size()];
|
||||
for (int i = 0; i < longs.length; i++) {
|
||||
longs[i] = list.get(i).longValue();
|
||||
}
|
||||
return longs;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
restore(); // 复原指针.
|
||||
}
|
||||
|
||||
List<Object> elementList = new ArrayList<>();
|
||||
|
||||
if (canRead() && peek() != LIST_END) {
|
||||
@@ -150,34 +100,6 @@ public final class SNBTReader extends DefaultStringReader {
|
||||
return elementList;
|
||||
}
|
||||
|
||||
// 解析数组 [I; 11, 41, 54]
|
||||
// ArrayType -> B, I, L.
|
||||
private Object parseArray(Function<List<Number>, Object> convertor) {
|
||||
skipWhitespace();
|
||||
// 用来暂存解析出的数字
|
||||
List<Number> elements = new ArrayList<>();
|
||||
if (canRead() && peek() != LIST_END) {
|
||||
do {
|
||||
Object element = parseValue();
|
||||
|
||||
// 1.21.6的SNBT原版是支持 {key:[B;1,2b,0xFF]} 这种奇葩写法的, 越界部分会被自动舍弃, 如0xff的byte值为-1.
|
||||
// 如果需要和原版对齐, 那么只需要判断是否是数字就行了.
|
||||
// if (!(element instanceof Number number))
|
||||
// throw new IllegalArgumentException("Error element type at pos " + getCursor());
|
||||
if (!(element instanceof Number number))
|
||||
throw new IllegalArgumentException("Error parsing number at pos " + getCursor());
|
||||
|
||||
elements.add(number); // 校验通过后加入
|
||||
skipWhitespace();
|
||||
} while (canRead() && peek() == ELEMENT_SEPARATOR && ++cursor > 0 /* 跳过 ',' */);
|
||||
}
|
||||
|
||||
if (!canRead() || peek() != LIST_END)
|
||||
throw new IllegalArgumentException("Expected ']' at position " + getCursor());
|
||||
skip(); // 跳过 ']'
|
||||
return convertor.apply(elements);
|
||||
}
|
||||
|
||||
// 解析Key值
|
||||
private String parseKey() {
|
||||
skipWhitespace();
|
||||
@@ -227,13 +149,12 @@ public final class SNBTReader extends DefaultStringReader {
|
||||
}
|
||||
}
|
||||
int tokenLength = getCursor() - tokenStart - lastWhitespace; // 计算值长度需要再减去尾部空格.
|
||||
if (tokenLength == 0) return null; // 如果值长度为0则返回null.
|
||||
if (tokenLength == 0) throw new IllegalArgumentException("Empty value at position " + tokenStart);
|
||||
if (contentHasWhitespace) return substring(tokenStart, tokenStart + tokenLength); // 如果值的中间有空格, 一定是字符串, 可直接返回.
|
||||
|
||||
// 布尔值检查
|
||||
if (tokenLength == 4) {
|
||||
if (matchesAt(tokenStart, "true")) return Boolean.TRUE;
|
||||
if (matchesAt(tokenStart, "null")) return null; // 支持 {key:null}.
|
||||
} else if (tokenLength == 5) {
|
||||
if (matchesAt(tokenStart, "false")) return Boolean.FALSE;
|
||||
}
|
||||
@@ -242,19 +163,19 @@ public final class SNBTReader extends DefaultStringReader {
|
||||
char lastChar = charAt(tokenStart + tokenLength - 1);
|
||||
try {
|
||||
switch (lastChar) {
|
||||
case 'b', 'B' -> {
|
||||
case BYTE_SUFFIX -> {
|
||||
return Byte.parseByte(substring(tokenStart, tokenStart + tokenLength - 1));
|
||||
}
|
||||
case 's', 'S' -> {
|
||||
case SHORT_SUFFIX -> {
|
||||
return Short.parseShort(substring(tokenStart, tokenStart + tokenLength - 1));
|
||||
}
|
||||
case 'l', 'L' -> {
|
||||
case LONG_SUFFIX -> {
|
||||
return Long.parseLong(substring(tokenStart, tokenStart + tokenLength - 1));
|
||||
}
|
||||
case 'f', 'F' -> {
|
||||
case FLOAT_SUFFIX -> {
|
||||
return Float.parseFloat(substring(tokenStart, tokenStart + tokenLength));
|
||||
}
|
||||
case 'd', 'D' -> {
|
||||
case DOUBLE_SUFFIX -> {
|
||||
return Double.parseDouble(substring(tokenStart, tokenStart + tokenLength));
|
||||
}
|
||||
default -> {
|
||||
|
||||
@@ -29,7 +29,6 @@ public class VersionHelper {
|
||||
private static final boolean v1_21_4;
|
||||
private static final boolean v1_21_5;
|
||||
private static final boolean v1_21_6;
|
||||
private static final boolean v1_21_7;
|
||||
|
||||
static {
|
||||
try (InputStream inputStream = Class.forName("net.minecraft.obfuscate.DontObfuscate").getResourceAsStream("/version.json")) {
|
||||
@@ -39,15 +38,15 @@ public class VersionHelper {
|
||||
JsonObject json = GsonHelper.parseJsonToJsonObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||
String versionString = json.getAsJsonPrimitive("id").getAsString();
|
||||
|
||||
MINECRAFT_VERSION = new MinecraftVersion(versionString.split("-", 2)[0]); // 确保去掉-rc1
|
||||
MINECRAFT_VERSION = new MinecraftVersion(versionString);
|
||||
|
||||
String[] split = versionString.split("\\.");
|
||||
int major = Integer.parseInt(split[1]);
|
||||
int minor = split.length == 3 ? Integer.parseInt(split[2].split("-", 2)[0]) : 0;
|
||||
|
||||
// 12001 = 1.20.1
|
||||
// 12104 = 1.21.4
|
||||
version = MINECRAFT_VERSION.version();
|
||||
// 2001 = 1.20.1
|
||||
// 2104 = 1.21.4
|
||||
version = parseVersionToInteger(versionString);
|
||||
|
||||
v1_20 = version >= 12000;
|
||||
v1_20_1 = version >= 12001;
|
||||
@@ -63,7 +62,6 @@ public class VersionHelper {
|
||||
v1_21_4 = version >= 12104;
|
||||
v1_21_5 = version >= 12105;
|
||||
v1_21_6 = version >= 12106;
|
||||
v1_21_7 = version >= 12107;
|
||||
|
||||
majorVersion = major;
|
||||
minorVersion = minor;
|
||||
@@ -211,8 +209,4 @@ public class VersionHelper {
|
||||
public static boolean isOrAbove1_21_6() {
|
||||
return v1_21_6;
|
||||
}
|
||||
|
||||
public static boolean isOrAbove1_21_7() {
|
||||
return v1_21_7;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user