diff --git a/README.md b/README.md index fefff6da4..941fceae5 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,14 @@

- - Gitbook - - Scc Count Badge + Scc Count Badge + + + Ask DeepWiki + + + Gitbook

diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index 607fff3b3..8e5ae6b27 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" id("maven-publish") } diff --git a/bukkit/legacy/build.gradle.kts b/bukkit/legacy/build.gradle.kts index ae80f6f46..da89d9df8 100644 --- a/bukkit/legacy/build.gradle.kts +++ b/bukkit/legacy/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" } repositories { diff --git a/bukkit/loader/build.gradle.kts b/bukkit/loader/build.gradle.kts index dae694cd2..83ddf1699 100644 --- a/bukkit/loader/build.gradle.kts +++ b/bukkit/loader/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta11" - id("net.minecrell.plugin-yml.bukkit") version "0.6.0" + id("com.gradleup.shadow") version "9.0.0-beta13" + id("de.eldoria.plugin-yml.bukkit") version "0.7.1" } repositories { @@ -25,7 +25,7 @@ dependencies { implementation("com.saicone.rtag:rtag-item:${rootProject.properties["rtag_version"]}") implementation("net.momirealms:sparrow-util:${rootProject.properties["sparrow_util_version"]}") implementation("net.momirealms:antigrieflib:${rootProject.properties["anti_grief_version"]}") - implementation("net.momirealms:craft-engine-nms-helper:${rootProject.properties["nms_helper_version"]}") + compileOnly("net.momirealms:craft-engine-nms-helper:${rootProject.properties["nms_helper_version"]}") } java { @@ -60,7 +60,7 @@ artifacts { tasks { shadowJar { - archiveFileName = "${rootProject.name}-plugin-${rootProject.properties["project_version"]}.jar" + archiveFileName = "${rootProject.name}-bukkit-plugin-${rootProject.properties["project_version"]}.jar" destinationDirectory.set(file("$rootDir/target")) relocate("net.kyori", "net.momirealms.craftengine.libraries") relocate("net.momirealms.sparrow.nbt", "net.momirealms.craftengine.libraries.nbt") diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java index 18d04e54c..31e379b78 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java @@ -122,6 +122,7 @@ public class ItemEventListener implements Listener { Block clickedBlock = Objects.requireNonNull(event.getClickedBlock()); BukkitServerPlayer player = this.plugin.adapt(bukkitPlayer); InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; + // 如果同一tick已经处理过交互,则忽略 if (cancelEventIfHasInteraction(event, player, hand)) { return; } @@ -132,6 +133,7 @@ public class ItemEventListener implements Listener { Optional> optionalItemBehaviors = itemInHand.getItemBehavior(); // has custom item behavior + // 物品类型是否包含自定义物品行为,行为不一定来自于自定义物品,部分原版物品也包含了新的行为 if (optionalItemBehaviors.isPresent()) { BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation()); Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ()); @@ -140,12 +142,17 @@ public class ItemEventListener implements Listener { boolean interactable = InteractUtils.isInteractable(BlockStateUtils.getBlockOwnerId(clickedBlock), bukkitPlayer, clickedBlock.getBlockData(), hitResult, itemInHand); // do not allow to place block if it's a vanilla block + // 如果这个是自定义物品,那么会阻止玩家放置其对应的原版方块 Optional> optionalCustomItem = itemInHand.getCustomItem(); if (itemInHand.isBlockItem() && optionalCustomItem.isPresent()) { // it's a custom item, but now it's ignored + // 如果用户设置了允许放置对应的原版方块,那么直接返回。 + // todo 实际上这里的处理并不正确,因为判断玩家是否能够放置那个方块需要更加细节的判断。比如玩家无法对着树叶放置火把,但是交互事件依然触发,此情况下不可丢弃自定义行为。 if (optionalCustomItem.get().settings().canPlaceRelatedVanillaBlock()) { return; } + // 如果玩家潜行放置或者交互对象不可交互,那么取消掉事件以防止玩家放置。 + // todo 这些处理应该要搬到BlockPlaceEvent? if (!interactable || player.isSecondaryUseActive()) { event.setCancelled(true); } @@ -180,10 +187,10 @@ public class ItemEventListener implements Listener { return; } } - return; } // it's a vanilla block + // 这部分代码是处理放置原版方块“缺失的”声音和挥手动画 if (itemInHand.isBlockItem() && !itemInHand.isCustomItem()) { // client won't have sounds if the fake block is interactable // so we should check and resend sounds on interact diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/classpath/BukkitClassPathAppender.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/classpath/BukkitClassPathAppender.java new file mode 100644 index 000000000..ddb3b04da --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/classpath/BukkitClassPathAppender.java @@ -0,0 +1,38 @@ +package net.momirealms.craftengine.bukkit.plugin.classpath; + +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.plugin.Plugin; +import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender; +import net.momirealms.craftengine.core.plugin.classpath.URLClassLoaderAccess; + +import java.net.MalformedURLException; +import java.net.URLClassLoader; +import java.nio.file.Path; + +public class BukkitClassPathAppender implements ClassPathAppender { + private final URLClassLoaderAccess classLoaderAccess; + + public BukkitClassPathAppender(ClassLoader classLoader) throws IllegalAccessException { + if (Reflections.clazz$PaperPluginClassLoader != null && Reflections.clazz$PaperPluginClassLoader.isInstance(classLoader)) { + URLClassLoader libraryClassLoader = (URLClassLoader) Reflections.field$PaperPluginClassLoader$libraryLoader.get(classLoader); + this.classLoaderAccess = URLClassLoaderAccess.create(libraryClassLoader); + } else if (classLoader instanceof URLClassLoader) { + this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) classLoader); + } else { + throw new IllegalStateException("ClassLoader is not instance of URLClassLoader"); + } + } + + public BukkitClassPathAppender(Plugin plugin) throws IllegalAccessException { + this(plugin.getClass().getClassLoader()); + } + + @Override + public void addJarToClasspath(Path file) { + try { + this.classLoaderAccess.addURL(file.toUri().toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index b1f33c52d..590515847 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -317,7 +317,6 @@ public class BukkitServerPlayer extends Player { public void tick() { // not fully online if (serverPlayer() == null) return; - if (VersionHelper.isFolia()) { try { Object serverPlayer = serverPlayer(); @@ -329,7 +328,7 @@ public class BukkitServerPlayer extends Player { } else { this.gameTicks = FastNMS.INSTANCE.field$MinecraftServer$currentTick(); } - if (this.gameTicks % 15 == 0) { + if (this.gameTicks % 30 == 0) { this.updateGUI(); } if (this.isDestroyingBlock) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 679a26279..cf7abd95b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -27,6 +27,7 @@ import sun.misc.Unsafe; import java.io.BufferedReader; import java.lang.invoke.VarHandle; import java.lang.reflect.*; +import java.net.URLClassLoader; import java.time.Instant; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -6675,4 +6676,12 @@ public class Reflections { public static final Constructor constructor$DiscardedPayload = Optional.ofNullable(clazz$DiscardedPayload) .map(clazz -> ReflectionUtils.getTheOnlyConstructor(clazz)) .orElse(null); + + public static final Class clazz$PaperPluginClassLoader = ReflectionUtils.getClazz( + "io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader" + ); + + public static final Field field$PaperPluginClassLoader$libraryLoader = Optional.ofNullable(clazz$PaperPluginClassLoader) + .map(it -> ReflectionUtils.getDeclaredField(it, URLClassLoader.class, 0)) + .orElse(null); } diff --git a/client-mod/build.gradle.kts b/client-mod/build.gradle.kts index df2efc2e3..083cc7ad4 100644 --- a/client-mod/build.gradle.kts +++ b/client-mod/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("fabric-loom") version "1.10-SNAPSHOT" - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" } version = property("project_version")!! diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 83e995a17..8b6a644d8 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" id("maven-publish") } @@ -52,9 +52,7 @@ dependencies { // Aho-Corasick java implementation compileOnly("org.ahocorasick:ahocorasick:${rootProject.properties["ahocorasick_version"]}") // Amazon S3 - compileOnly("software.amazon.awssdk:s3:${rootProject.properties["amazon_awssdk_version"]}") { - - } + compileOnly("software.amazon.awssdk:s3:${rootProject.properties["amazon_awssdk_version"]}") compileOnly("software.amazon.awssdk:netty-nio-client:${rootProject.properties["amazon_awssdk_version"]}") // EvalEx compileOnly("com.ezylang:EvalEx:${rootProject.properties["evalex_version"]}") diff --git a/server-mod/v1_20_1/build.gradle.kts b/server-mod/v1_20_1/build.gradle.kts index 8589cbe10..0266dd510 100644 --- a/server-mod/v1_20_1/build.gradle.kts +++ b/server-mod/v1_20_1/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("java-library") - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" } diff --git a/server-mod/v1_20_5/build.gradle.kts b/server-mod/v1_20_5/build.gradle.kts index 272257de9..db31453d2 100644 --- a/server-mod/v1_20_5/build.gradle.kts +++ b/server-mod/v1_20_5/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("java-library") - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" } diff --git a/server-mod/v1_21_5/build.gradle.kts b/server-mod/v1_21_5/build.gradle.kts index 0be3a008a..617f52ce2 100644 --- a/server-mod/v1_21_5/build.gradle.kts +++ b/server-mod/v1_21_5/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("java-library") - id("com.gradleup.shadow") version "9.0.0-beta11" + id("com.gradleup.shadow") version "9.0.0-beta13" id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" } diff --git a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java index 8b3039c7b..cec744de3 100644 --- a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java +++ b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java @@ -5,13 +5,18 @@ import net.minecraft.core.Direction; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.momirealms.craftengine.mod.CraftEnginePlugin; @@ -23,7 +28,6 @@ import org.jetbrains.annotations.NotNull; public class CraftEngineBlock extends Block implements BehaviorHolder, ShapeHolder, NoteBlockIndicator, Fallable, BonemealableBlock - //TODO , SimpleWaterloggedBlock { private static final StoneBlockShape STONE = new StoneBlockShape(Blocks.STONE.defaultBlockState()); private boolean isNoteBlock; @@ -146,14 +150,14 @@ public class CraftEngineBlock } @Override - protected BlockState updateShape(@NotNull BlockState state, - @NotNull LevelReader level, - @NotNull ScheduledTickAccess scheduledTickAccess, - @NotNull BlockPos pos, - @NotNull Direction direction, - @NotNull BlockPos neighborPos, - @NotNull BlockState neighborState, - @NotNull RandomSource random) { + protected @NotNull BlockState updateShape(@NotNull BlockState state, + @NotNull LevelReader level, + @NotNull ScheduledTickAccess scheduledTickAccess, + @NotNull BlockPos pos, + @NotNull Direction direction, + @NotNull BlockPos neighborPos, + @NotNull BlockState neighborState, + @NotNull RandomSource random) { try { if (isNoteBlock && level instanceof ServerLevel serverLevel) { startNoteBlockChain(direction, serverLevel, pos); @@ -189,16 +193,6 @@ public class CraftEngineBlock } } -// @Override -// protected @NotNull FluidState getFluidState(@NotNull BlockState state) { -// try { -// return (FluidState) behaviorHolder.value().getFluidState(this, new Object[]{state}, () -> super.getFluidState(state)); -// } catch (Exception e) { -// e.printStackTrace(); -// return super.getFluidState(state); -// } -// } - @Override public boolean isValidBonemealTarget(@NotNull LevelReader levelReader, @NotNull BlockPos blockPos, @NotNull BlockState blockState) { try { @@ -236,35 +230,24 @@ public class CraftEngineBlock e.printStackTrace(); } } - +// // @Override -// public boolean canPlaceLiquid(@Nullable Player player, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull Fluid fluid) { +// protected @NotNull InteractionResult useWithoutItem(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull Player player, @NotNull BlockHitResult hitResult) { // try { -// return behaviorHolder.value().canPlaceLiquid(this, new Object[]{player, level, pos, state, fluid}, () -> SimpleWaterloggedBlock.super.canPlaceLiquid(player, level, pos, state, fluid)); +// return (InteractionResult) behaviorHolder.value().useWithoutItem(this, new Object[]{state, level, pos, player, hitResult}, () -> super.useWithoutItem(state, level, pos, player, hitResult)); // } catch (Exception e) { // e.printStackTrace(); -// return SimpleWaterloggedBlock.super.canPlaceLiquid(player, level, pos, state, fluid); +// return super.useWithoutItem(state, level, pos, player, hitResult); // } // } // // @Override -// public boolean placeLiquid(@NotNull LevelAccessor level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull FluidState fluidState) { +// protected @NotNull InteractionResult useItemOn(@NotNull ItemStack stack, @NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) { // try { -// return behaviorHolder.value().placeLiquid(this, new Object[]{level, pos, state, fluidState}, () -> SimpleWaterloggedBlock.super.placeLiquid(level, pos, state, fluidState)); +// return (InteractionResult) behaviorHolder.value().useItemOn(this, new Object[]{stack, stack, level, pos, player, hand, hitResult}, () -> super.useItemOn(stack, state, level, pos, player, hand, hitResult)); // } catch (Exception e) { // e.printStackTrace(); -// return SimpleWaterloggedBlock.super.placeLiquid(level, pos, state, fluidState); -// } -// } -// -// @NotNull -// @Override -// public ItemStack pickupBlock(@Nullable Player player, @NotNull LevelAccessor level, @NotNull BlockPos pos, @NotNull BlockState state) { -// try { -// return (ItemStack) behaviorHolder.value().pickupBlock(this, new Object[]{player, level, pos, state}, () -> SimpleWaterloggedBlock.super.pickupBlock(player, level, pos, state)); -// } catch (Exception e) { -// e.printStackTrace(); -// return SimpleWaterloggedBlock.super.pickupBlock(player, level, pos, state); +// return super.useItemOn(stack, state, level, pos, player, hand, hitResult); // } // } } diff --git a/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java b/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java index 67c22fbd8..c48115996 100644 --- a/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java +++ b/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java @@ -4,6 +4,14 @@ import java.util.concurrent.Callable; public abstract class BlockBehavior { +// public Object useItemOn(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return superMethod.call(); +// } +// +// public Object useWithoutItem(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return superMethod.call(); +// } + public Object rotate(Object thisBlock, Object[] args, Callable superMethod) throws Exception { return superMethod.call(); }