PixelEast
我正在写一个类似Hypixel Bedwars中海绵效果的插件,但是我发现好像没有办法阻止原版海绵吸水的行为
如何实现阻止海绵的吸水行为?

服务端版本为1.8.8 Paper

希望能够给出关键的实现代码


就叫谷姐吧
如果没有特殊需求,监听BlockPlaceEvent事件,也就是方块放置,如果是干海绵的话就取消,这样应该就行了

PixelEast
就叫谷姐吧 发表于 2023-11-25 15:45
如果没有特殊需求,监听BlockPlaceEvent事件,也就是方块放置,如果是干海绵的话就取消,这样应该就行了 ...

我需要实现的是放置出来的海绵没有原版的吸水特性,或者说阻止原版的吸水特性

就叫谷姐吧
PixelEast 发表于 2023-11-25 15:47
我需要实现的是放置出来的海绵没有原版的吸水特性,或者说阻止原版的吸水特性 ...

bukkit好像并没有提供海绵吸水事件o o

nsju7

复制代码

PixelEast
就叫谷姐吧 发表于 2023-11-25 15:50
还是监听BlockPlaceEvent,先判断方块是不是干海绵,如果是就取消事件,然后自行代替这个事件应该就行了
...

这个我已经尝试过了,但不是最优解,我更喜欢放置出来的方块是海绵而不是湿海绵,我猜这个部分要实现可能与方块更新抑制有关

名副其实
https://www.spigotmc.org/threads ... -absorption.311036/

PixelEast
名副其实 发表于 2023-11-25 16:13
https://www.spigotmc.org/threads/cancel-sponge-water-absorption.311036/

这个我也尝试过了,但它并不管用,也可能是我的实现存在错误

huzpsb
PixelEast 发表于 2023-11-25 16:02
这个我已经尝试过了,但不是最优解,我更喜欢放置出来的方块是海绵而不是湿海绵,我猜这个部分要实现可能 ...

呃 那就用fawe-api异步放置一个。这样放出来的海绵是干的。

Bukkit 并未提供相关 API,因此在不使用发包或修改服务端本体的前提下,只能使用 非常暴力不知道会有什么后果 的手段解决该问题。
以下代码基于 TabooLib & Kotlin,功能并不完善,仅演示基本功能。

  1. import net.minecraft.server.v1_8_R3.*
  2. import org.bukkit.Material
  3. import org.bukkit.event.block.BlockPhysicsEvent
  4. import org.bukkit.event.block.BlockPlaceEvent
  5. import taboolib.common.platform.event.SubscribeEvent
  6. import taboolib.common.platform.function.submit
  7. import taboolib.library.reflex.Reflex.Companion.getProperty
  8. import taboolib.library.reflex.Reflex.Companion.setProperty

  9. object SpongeFix {

  10.     @SubscribeEvent
  11.     private fun onPlace(e: BlockPlaceEvent) {
  12.         // 基本逻辑:
  13.         // 1. 在放下方块时,将整个游戏的海绵默认设置为吸水状态
  14.         // 2. 已知 Blocks.SPONGE.blockData 实际为 BlockStateList$BlockData
  15.         // 3. 获取字段 private final ImmutableMap<IBlockState, Comparable> b;
  16.         // 4. 强行修改 ImmutableMap(实际为 SingletonImmutableBiMap)的值
  17.         // 注:getProperty 是 TabooLib 的反射函数,可以理解为 getField + get
  18.         Blocks.SPONGE.blockData.getProperty<Any>("b")!!.setProperty("singleValue", true)
  19.         submit(delay = 1) {
  20.             // 放下后恢复,否则服务端会在 interact 事件下报错
  21.             Blocks.SPONGE.blockData.getProperty<Any>("b")!!.setProperty("singleValue", false)
  22.         }
  23.     }

  24.     @SubscribeEvent
  25.     private fun onPhysics(e: BlockPhysicsEvent) {
  26.         // 玩家放下的实际是干海绵,因此在破坏相邻方块时会触发物理事件,导致海绵吸水
  27.         if (e.block.type == Material.SPONGE) {
  28.             // 你先别吸
  29.             e.isCancelled = true
  30.         }
  31.     }
  32. }
复制代码