diff --git a/README.md b/README.md
index fefff6da4..941fceae5 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,14 @@
-
-
-
-
+
+
+
+
+
+
+
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