diff --git a/AGENTS.md b/AGENTS.md index b97d6a0..655fb8b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # sfcraft Agent 工作指南 -Fabric **纯服务端** mod,Minecraft **26.2**,Java 25,官方 Mojang 映射,自定义内容经 [Polymer](https://polymer.pb4.eu) 伪装成原版内容。整体结构见 [ARCHITECTURE.md](./ARCHITECTURE.md),先读它再动代码。 +Fabric **纯服务端** mod,Minecraft **26.3**,Java 25,官方 Mojang 映射,自定义内容经 [Polymer](https://polymer.pb4.eu) 伪装成原版内容。整体结构见 [ARCHITECTURE.md](./ARCHITECTURE.md),先读它再动代码。 ## ⚠️ 工作范围(最高优先级规则) @@ -22,23 +22,22 @@ Agent 的主要工作范围**只有**这两个包: ## 工具使用 - 探索、读写代码**优先使用 IDE 的 MCP 工具**:`list_directory_tree`(代替 `ls`/`find`)、`read_file`(代替 `cat`/`sed`)、`search_text`/`search_regex`/`search_symbol`(代替 `rg`/`grep`)、`get_symbol_info`、`analyze_calls`;编辑用 `apply_patch`/`create_new_file`。 -- 查 26.2 原版类签名**优先用 `read_file` 直接读 loom 缓存 jar 内的类**(会反编译,可读上下文):`~/.gradle/caches/fabric-loom/minecraftMaven/net/minecraft/minecraft-merged-deobf/26.2/minecraft-merged-deobf-26.2.jar!/net/minecraft/.../SomeClass.class`,`javap` 仅作回退。 +- 查 26.3 原版类签名**优先用 `read_file` 直接读 loom 缓存 jar 内的类**(会反编译,可读上下文):`~/.gradle/caches/fabric-loom/minecraftMaven/net/minecraft/minecraft-merged-deobf/26.3/minecraft-merged-deobf-26.3.jar!/net/minecraft/.../SomeClass.class`,`javap` 仅作回退。 - shell 只留给 MCP 做不了的事:gradle 编译/运行、git、文件权限操作等。 ## 构建与验证 -仓库**没有** gradlew wrapper,使用系统 gradle + sdkman JDK: +仓库自带 gradlew wrapper(**9.7.1** —— loom 1.18.x 要求 Gradle ≥ 9.7,Dockerfile 也走 `./gradlew`): ```bash -export JAVA_HOME=~/.sdkman/candidates/java/25.0.1-amzn -~/.sdkman/candidates/gradle/9.6.0/bin/gradle compileJava --console=plain # 编译(mixin AP 会校验注入目标) -~/.sdkman/candidates/gradle/9.6.0/bin/gradle runServer --console=plain # dev 服务器(run/ 目录,EULA 已接受) +./gradlew compileJava --console=plain # 编译(mixin AP 会校验注入目标) +./gradlew runServer --console=plain # dev 服务器(run/ 目录,EULA 已接受) ``` -查 26.2 真实签名(解决 cannot find symbol 的最快办法): +查 26.3 真实签名(解决 cannot find symbol 的最快办法): ```bash -javap -cp ~/.gradle/caches/fabric-loom/minecraftMaven/net/minecraft/minecraft-merged-deobf/26.2/minecraft-merged-deobf-26.2.jar <类全名> +javap -cp ~/.gradle/caches/fabric-loom/minecraftMaven/net/minecraft/minecraft-merged-deobf/26.3/minecraft-merged-deobf-26.3.jar <类全名> ``` ## 新增/修改玩法特性的套路 @@ -65,6 +64,17 @@ javap -cp ~/.gradle/caches/fabric-loom/minecraftMaven/net/minecraft/minecraft-me ## 踩过的坑 +**26.3 变更**(相对 26.2,本次移植踩到的;写代码前先 javap 确认): + +- **方块 codec 体系整个删了**:`Block` 不再有 `MapCodec CODEC` / `codec()`,`simpleCodec()` 也没了 —— 自定义方块直接删掉这两段即可(原版 `LayeredCauldronBlock` 同样已无 codec) +- `Entity.hurtMarked` 字段 → **`Entity.syncVelocity`**(仍是 public 字段,纯改名);`markHurt()` 照旧 protected +- `LivingEntity.drop(ItemStack, boolean)` → **`drop(ItemStack, boolean, Prediction)`**(`net.minecraft.util.Prediction`,枚举 `PREDICTED`/`SERVER_ONLY`)。服务端逻辑自己发起的掉落用 `SERVER_ONLY`,客户端没预测过 +- `Entity.canSimulateMovement()` 变 **final**,改写点移到 **`getMoveSimulationType()`**(返回 `MoveSimulationType`,默认 `AUTHORITATIVE_SIDE`)。想让服务端始终模拟(纯服务端坐骑)返回 `AUTHORITATIVE_SIDE_AND_SERVER` +- 战利品数字提供器拆成 `providers.number.ints` / `.floats` 两个子包,且全部 `Holder` 化:`UniformGenerator.between(1.0F, 3.0F)` → **`ContextIntProviders.between(1, 3)`**(返回 `Holder`,`SetItemCountFunction.setCount` 现在收的就是它) +- `BonemealableBlock` 三个方法都多了一个 **`BonemealSource`** 参数(`INTERACTION`/`MOB`) +- `MinecraftServer.clockManager()` 的 `getTotalTicks(clock)` 没了 → **`clockManager().getInstance(clock).totalTicks()`**(`ClockInstance` 接口:`totalTicks/partialTick/rate/isPaused`);`addTicks`/`setTotalTicks` 等写操作仍在 manager 上 +- `EnderMan` → **`Enderman`**(只是大小写,包没动) + **26.2 Mojmap 重命名**(相对 1.21.x,写代码前先 javap 确认): - `ResourceLocation` → `net.minecraft.resources.Identifier`(`Identifier.fromNamespaceAndPath`) @@ -76,7 +86,7 @@ javap -cp ~/.gradle/caches/fabric-loom/minecraftMaven/net/minecraft/minecraft-me - `MobEffects.SLOWNESS`(不是 MOVEMENT_SLOWDOWN);`SimpleContainer` 没有 addListener 了(覆写 `setChanged()` 持久化) - `GameProfile` 是 record(`name()`/`id()`);`sendOverlayMessage`/`sendSystemMessage` 取代 `displayClientMessage`;命令权限 `Commands.LEVEL_GAMEMASTERS.check(source.permissions())` -**Polymer(0.17.3+26.2)**: +**Polymer(0.18.0+26.3-rc-1 —— 上游还没出 26.3 正式版构建,先用 rc-1 那版)**: - `PacketContext` 在 `net.fabricmc.fabric.api.networking.v1.context.PacketContext` - BE 类型必须 `PolymerBlockUtils.registerBlockEntity`,实体类型必须 `PolymerEntityUtils.registerType`(`RegistryHelper` 已封装) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 954c137..be0d21a 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,6 +1,6 @@ # SFCraft 架构 -Fabric **纯服务端** mod(`fabric.mod.json` 中 `environment: "server"`),Minecraft **26.2**,Java 25,**官方 Mojang 映射**。所有自定义内容通过 [Polymer](https://polymer.pb4.eu) 伪装成原版内容;玩家使用原版客户端 + 服务器发布的材质包即可游玩。 +Fabric **纯服务端** mod(`fabric.mod.json` 中 `environment: "server"`),Minecraft **26.3**,Java 25,**官方 Mojang 映射**。所有自定义内容通过 [Polymer](https://polymer.pb4.eu) 伪装成原版内容;玩家使用原版客户端 + 服务器发布的材质包即可游玩。 ## 分层 diff --git a/Dockerfile b/Dockerfile index 06483c6..cd40447 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,14 +14,24 @@ RUN cd /mod && \ cp /mod/build/libs/sfcraft-*-all.jar /sfcraft.jar FROM base AS justbackup-builder -RUN git clone https://github.com/saltedfishclub/justbackup /mod +# 跟随 MC 版本的分支。26.3 分支需先在上游仓库建好,否则此处会直接失败—— +# 这是刻意的:默认分支仍是 26.2(fabric.mod.json 要求 minecraft ~26.2), +# 构建进 26.3 镜像只会在加载时才报错,不如在构建期暴露。 +ARG JUSTBACKUP_REF=26.3 +RUN git clone -b "$JUSTBACKUP_REF" https://github.com/saltedfishclub/justbackup /mod RUN cd /mod && \ ./gradlew build && \ rm -f /mod/build/libs/*sources.jar /mod/build/libs/*dev.jar && \ - cp /mod/build/libs/justbackup-1.0.0.jar /justbackup.jar + cp /mod/build/libs/justbackup-*.jar /justbackup.jar FROM base AS carpet-builder -RUN git clone https://github.com/saltedfishclub/fabric-carpet /mod +# 同上。carpet 的 depends 写的是 minecraft >26.2,能装上但 mixin 是按旧版编译的, +# 跑在 26.3 上会在 mixin apply 阶段炸,所以同样必须切到 26.3 分支。 +# ⚠️ 注意:26.3 分支目前只是合了上游 master,而上游自己还停在 26.3-snapshot-9 +# (对 26.3 正式版有 100+ 处编译错误)。等 gnembon 跟上 26.3 正式版、我们再合一次 +# 之前,这一层产出的 carpet 装进 26.3 服务器大概率仍然会崩。 +ARG CARPET_REF=26.3 +RUN git clone -b "$CARPET_REF" https://github.com/saltedfishclub/fabric-carpet /mod RUN cd /mod && \ ./gradlew build && \ rm -f /mod/build/libs/*sources.jar /mod/build/libs/*dev.jar && \ diff --git a/build.gradle b/build.gradle index 9ed98e2..35ec42a 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'maven-publish' id("io.freefair.lombok") version "9.5.0" id("com.gradleup.shadow") version "9.3.1" - id 'net.fabricmc.fabric-loom' version '1.17-SNAPSHOT' + id 'net.fabricmc.fabric-loom' version '1.18.1' } version = project.mod_version @@ -37,7 +37,7 @@ dependencies { shadow("org.apache.commons:commons-compress:1.28.0") shadow("io.ib67.kiwi:lang:1.2.3-SNAPSHOT") shadow('com.github.houbb:pinyin:0.4.0') - def polymerVersion = "0.17.3+26.2" + def polymerVersion = "0.18.0+26.3-rc-1" implementation include("eu.pb4:polymer-core:$polymerVersion") implementation include("eu.pb4:polymer-virtual-entity:$polymerVersion") implementation include("eu.pb4:polymer-resource-pack:$polymerVersion") diff --git a/gradle.properties b/gradle.properties index d94eb2a..2f04609 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx2G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=26.2 -loader_version=0.19.3 +minecraft_version=26.3 +loader_version=0.19.5 # Mod Properties @@ -14,4 +14,4 @@ archives_base_name=sfcraft # Dependencies # check this on https://modmuss50.me/fabric.html -fabric_version=0.155.0+26.2 +fabric_version=0.160.5+26.3 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a950f0b..9a2adaf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Jul 22 12:25:27 GMT+08:00 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/server-deploy/overrides/sfcraft/motd.txt b/server-deploy/overrides/sfcraft/motd.txt index 8377061..2812174 100644 --- a/server-deploy/overrides/sfcraft/motd.txt +++ b/server-deploy/overrides/sfcraft/motd.txt @@ -1,2 +1,2 @@ -§b§lSaltedFish Club Server §r§8| §f26.2 §c§lv2.2 +§b§lSaltedFish Club Server §r§8| §f26.3 §c§lv2.2 §8§lINVITED PLAYERS ONLY. 服务器启用白名单. \ No newline at end of file diff --git a/server-deploy/pack/index.toml b/server-deploy/pack/index.toml index 115a97b..e771126 100644 --- a/server-deploy/pack/index.toml +++ b/server-deploy/pack/index.toml @@ -2,7 +2,7 @@ hash-format = "sha256" [[files]] file = "mods/fabric-api.pw.toml" -hash = "dc5490cc1a9231b0d32ec3e72f9d34279fc1d1ff6fb5a7d288b1f36faec0a6a0" +hash = "e3a8b560330802ec556f34a7de7a73bc712202359a657a36b39e6f85598bf8b8" metafile = true [[files]] @@ -47,12 +47,12 @@ metafile = true [[files]] file = "mods/polymer.pw.toml" -hash = "2a5626a6d9b61f968f294466e9756fbafa1c1208b4fb53c53cfc8d2afb42a857" +hash = "2dec8c17d9d6fdf6dd93e2dc458c8d30ead86b2efc292490142841aacd4d3e95" metafile = true [[files]] file = "mods/simple-voice-chat.pw.toml" -hash = "be7369da963f5326a771bbfa360365ac6ed939b01c2c268f4dd4a922718cd4a3" +hash = "e55e25489644c7297a7f4cda6618437891fd0aba88e7f670a0439c3eadc14fc0" metafile = true [[files]] diff --git a/server-deploy/pack/mods/fabric-api.pw.toml b/server-deploy/pack/mods/fabric-api.pw.toml index 385a7ba..c386b4a 100644 --- a/server-deploy/pack/mods/fabric-api.pw.toml +++ b/server-deploy/pack/mods/fabric-api.pw.toml @@ -1,13 +1,13 @@ name = "Fabric API" -filename = "fabric-api-0.155.2+26.2.jar" +filename = "fabric-api-0.160.5+26.3.jar" side = "both" [download] -url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/lVXlbH4w/fabric-api-0.155.2%2B26.2.jar" +url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/oCYG2H4L/fabric-api-0.160.5%2B26.3.jar" hash-format = "sha512" -hash = "cc56984378a27c5bcd56374d6ffbb27a45c6bf3355add2ac6be9817ccac5854362249bf9d0147eb271a70fda2716129204e240d53c9aa876a2a7861f4c7f880f" +hash = "494378477dd9571f49c27cc1eaee3f78f140b9d8bd860c757f453bee198fd5b8a9eee444069c595b0fb6f8cb6bc86d51ccddbcec8d782fd46ef2fb1d9ac22f16" [update] [update.modrinth] mod-id = "P7dR8mSH" -version = "lVXlbH4w" +version = "oCYG2H4L" diff --git a/server-deploy/pack/mods/polymer.pw.toml b/server-deploy/pack/mods/polymer.pw.toml index 75a080a..a26a911 100644 --- a/server-deploy/pack/mods/polymer.pw.toml +++ b/server-deploy/pack/mods/polymer.pw.toml @@ -1,13 +1,13 @@ name = "Polymer" -filename = "polymer-bundled-0.17.3+26.2.jar" +filename = "polymer-bundled-0.18.0+26.3-rc-1.jar" side = "both" [download] -url = "https://cdn.modrinth.com/data/xGdtZczs/versions/w0N4I45x/polymer-bundled-0.17.3%2B26.2.jar" +url = "https://cdn.modrinth.com/data/xGdtZczs/versions/QBYrHLvh/polymer-bundled-0.18.0%2B26.3-rc-1.jar" hash-format = "sha512" -hash = "1459edf99834bbbb2eff5f7df2e7159688ad88e20e8704bc473752e81a755963bb96c511641d53c9f7b4e5867436f7b49ef839e3b857c48ca54af93627c2a110" +hash = "59cc2d99ead79e71b1b9df0751157f42cecf3cb0d67b4e9494ffe256e9375d9c111c7d126cc6a73161e16c39b6d5c87090aac5468ab08cd8982ed1ba55134869" [update] [update.modrinth] mod-id = "xGdtZczs" -version = "w0N4I45x" +version = "QBYrHLvh" diff --git a/server-deploy/pack/mods/simple-voice-chat.pw.toml b/server-deploy/pack/mods/simple-voice-chat.pw.toml index fd916d5..1e6d2d1 100644 --- a/server-deploy/pack/mods/simple-voice-chat.pw.toml +++ b/server-deploy/pack/mods/simple-voice-chat.pw.toml @@ -1,13 +1,13 @@ name = "Simple Voice Chat" -filename = "voicechat-fabric-2.6.21+26.2.jar" +filename = "voicechat-fabric-2.6.23+26.3.jar" side = "both" [download] -url = "https://cdn.modrinth.com/data/9eGKb6K1/versions/3SOh5iiX/voicechat-fabric-2.6.21%2B26.2.jar" +url = "https://cdn.modrinth.com/data/9eGKb6K1/versions/3fRw6NfP/voicechat-fabric-2.6.23%2B26.3.jar" hash-format = "sha512" -hash = "0308b2e18a05913faaf461530a475d2f5debbfb4d0a46107b512ce51166ceb6cfdbea468f7e21444a3e005655e51729c3764266f81c59b6228629b4866d16b28" +hash = "fd62ca0b4048ab855e7f2436ecdf6c7301e546946afe2d7a3dfa3fb7c180636cbd971c0e9c5e62be4a86d67bbed54fa62ab4d4680c47ea0b366e49b9202ff42a" [update] [update.modrinth] mod-id = "9eGKb6K1" -version = "3SOh5iiX" +version = "3fRw6NfP" diff --git a/server-deploy/pack/pack.toml b/server-deploy/pack/pack.toml index 0f3f21f..d2fbaa9 100644 --- a/server-deploy/pack/pack.toml +++ b/server-deploy/pack/pack.toml @@ -6,11 +6,11 @@ pack-format = "packwiz:1.1.0" [index] file = "index.toml" hash-format = "sha256" -hash = "d7c215cba51d8e9324316d5c236c6f03727012917340b2100c868614170ba69e" +hash = "7524eced8051fa2ae3e84ae584afcf9863dd121db99555618b517447540daed1" [versions] -fabric = "0.19.3" -minecraft = "26.2" +fabric = "0.19.5" +minecraft = "26.3" [options] -acceptable-game-versions = ["26.1", "26.1.2"] +acceptable-game-versions = ["26.2"] diff --git a/src/main/java/io/ib67/sfcraft/mixin/common/fixes/EndermanEntityMixin.java b/src/main/java/io/ib67/sfcraft/mixin/common/fixes/EndermanEntityMixin.java index 9f7ee2e..82b8d79 100644 --- a/src/main/java/io/ib67/sfcraft/mixin/common/fixes/EndermanEntityMixin.java +++ b/src/main/java/io/ib67/sfcraft/mixin/common/fixes/EndermanEntityMixin.java @@ -1,13 +1,13 @@ package io.ib67.sfcraft.mixin.common.fixes; import io.ib67.sfcraft.mixin.common.MobEntityMixin; -import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Enderman; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(EnderMan.class) +@Mixin(Enderman.class) public abstract class EndermanEntityMixin extends MobEntityMixin { @Inject(at = @At("HEAD"), method = "requiresCustomPersistence", cancellable = true) private void sf$cannotDespawn(CallbackInfoReturnable cir) { diff --git a/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/HoglinMountMixin.java b/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/HoglinMountMixin.java index 216adf1..efdd656 100644 --- a/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/HoglinMountMixin.java +++ b/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/HoglinMountMixin.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.entity.MoveSimulationType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -78,10 +79,12 @@ public abstract class HoglinMountMixin extends Animal implements MountAccess { } @Override - public boolean canSimulateMovement() { - // 骑手是 Player 时会被判为客户端权威,但纯服务端坐骑客户端不会模拟 → 强制服务端模拟 - if (!level().isClientSide() && getControllingPassenger() != null) return true; - return super.canSimulateMovement(); + public MoveSimulationType getMoveSimulationType() { + // 骑手是 Player 时会被判为客户端权威,但纯服务端坐骑客户端不会模拟 → 强制服务端模拟。 + // 26.3 起 canSimulateMovement() 变 final,改写点移到这里:AUTHORITATIVE_SIDE_AND_SERVER + // 的语义就是"服务端永远模拟 + 权威端模拟",等价于原来的 !isClientSide 分支。 + if (getControllingPassenger() != null) return MoveSimulationType.AUTHORITATIVE_SIDE_AND_SERVER; + return super.getMoveSimulationType(); } @Override diff --git a/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/RavagerMountMixin.java b/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/RavagerMountMixin.java index d611593..e5bdf5d 100644 --- a/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/RavagerMountMixin.java +++ b/src/main/java/io/ib67/sfcraft/mixin/gameplay/mount/RavagerMountMixin.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.entity.MoveSimulationType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -82,10 +83,12 @@ public abstract class RavagerMountMixin extends Raider implements MountAccess { } @Override - public boolean canSimulateMovement() { - // 骑手是 Player 时会被判为客户端权威,但纯服务端坐骑客户端不会模拟 → 强制服务端模拟 - if (!level().isClientSide() && getControllingPassenger() != null) return true; - return super.canSimulateMovement(); + public MoveSimulationType getMoveSimulationType() { + // 骑手是 Player 时会被判为客户端权威,但纯服务端坐骑客户端不会模拟 → 强制服务端模拟。 + // 26.3 起 canSimulateMovement() 变 final,改写点移到这里:AUTHORITATIVE_SIDE_AND_SERVER + // 的语义就是"服务端永远模拟 + 权威端模拟",等价于原来的 !isClientSide 分支。 + if (getControllingPassenger() != null) return MoveSimulationType.AUTHORITATIVE_SIDE_AND_SERVER; + return super.getMoveSimulationType(); } @Override diff --git a/src/main/java/io/ib67/sfcraft/module/FartFertilizerModule.java b/src/main/java/io/ib67/sfcraft/module/FartFertilizerModule.java index 5a1fc22..8ebe411 100644 --- a/src/main/java/io/ib67/sfcraft/module/FartFertilizerModule.java +++ b/src/main/java/io/ib67/sfcraft/module/FartFertilizerModule.java @@ -16,6 +16,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.BonemealableBlock; +import net.minecraft.world.level.block.BonemealSource; public class FartFertilizerModule extends ServerModule { private final Object2LongMap lastSneaked = new Object2LongOpenHashMap<>(); @@ -63,7 +64,7 @@ public class FartFertilizerModule extends ServerModule { } if (player.getRandom().nextInt(10) < 3) { ((BonemealableBlock) block).performBonemeal(wld, - wld.getRandom(), blockPos, state); + wld.getRandom(), blockPos, state, BonemealSource.INTERACTION); } } } diff --git a/src/main/java/io/ib67/sfcraft/module/game/bomb/BombModule.java b/src/main/java/io/ib67/sfcraft/module/game/bomb/BombModule.java index 9c11ebb..0e512d8 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/bomb/BombModule.java +++ b/src/main/java/io/ib67/sfcraft/module/game/bomb/BombModule.java @@ -20,7 +20,7 @@ import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.entries.LootItem; import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; import net.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceCondition; -import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; +import net.minecraft.world.level.storage.loot.providers.number.ints.ContextIntProviders; /** * 三种投掷炸弹(普通/黑曜石/烈焰)与它们的战利品注入(地牢箱、苦力怕掉落)。 @@ -76,11 +76,11 @@ public class BombModule extends ServerModule { tableBuilder.withPool(LootPool.lootPool() .when(LootItemRandomChanceCondition.randomChance(loot.dungeonBombChance)) .add(LootItem.lootTableItem(bomb) - .apply(SetItemCountFunction.setCount(UniformGenerator.between(1.0F, 3.0F))))); + .apply(SetItemCountFunction.setCount(ContextIntProviders.between(1, 3))))); tableBuilder.withPool(LootPool.lootPool() .when(LootItemRandomChanceCondition.randomChance(loot.dungeonObsidianBombChance)) .add(LootItem.lootTableItem(obsidianBomb) - .apply(SetItemCountFunction.setCount(UniformGenerator.between(1.0F, 2.0F))))); + .apply(SetItemCountFunction.setCount(ContextIntProviders.between(1, 2))))); } EntityTypes.CREEPER.getDefaultLootTable().ifPresent(creeperTable -> { if (creeperTable.equals(key)) { diff --git a/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlock.java b/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlock.java index 0f37f8a..740db07 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlock.java +++ b/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlock.java @@ -1,6 +1,5 @@ package io.ib67.sfcraft.module.game.cauldron; -import com.mojang.serialization.MapCodec; import eu.pb4.polymer.core.api.block.PolymerBlock; import eu.pb4.polymer.virtualentity.api.BlockWithElementHolder; import eu.pb4.polymer.virtualentity.api.ElementHolder; @@ -37,7 +36,6 @@ import java.util.function.BiFunction; public class AmethystCauldronBlock extends BaseEntityBlock implements PolymerBlock, BlockWithElementHolder { public static final BooleanProperty HAS_WATER = BooleanProperty.create("has_water"); - public static final MapCodec CODEC = simpleCodec(AmethystCauldronBlock::new); // Polymer 会把该偏移加到方块中心(Vec3.atCenterOf), 因此这里是相对中心的偏移: // 结果约为 (x+0.5, y+0.55, z+0.5), 即锅内水中、锅沿以下、水平居中。 private static final Vec3 ELEMENT_HOLDER_OFFSET = new Vec3(0.0, 0.05, 0.0); @@ -57,11 +55,6 @@ public class AmethystCauldronBlock extends BaseEntityBlock implements PolymerBlo this.blockEntityFactory = factory; } - @Override - protected @NonNull MapCodec codec() { - return CODEC; - } - @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(HAS_WATER); diff --git a/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlockEntity.java b/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlockEntity.java index 08a8f50..ef4f17a 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlockEntity.java +++ b/src/main/java/io/ib67/sfcraft/module/game/cauldron/AmethystCauldronBlockEntity.java @@ -25,6 +25,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.AABB; +import net.minecraft.util.Prediction; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -124,7 +125,7 @@ public class AmethystCauldronBlockEntity extends BlockEntity { if (contents.isEmpty()) return InteractionResult.PASS; var stack = contents.removeLast(); if (!player.getInventory().add(stack)) { - player.drop(stack, false); + player.drop(stack, false, Prediction.SERVER_ONLY); } level.playSound(null, getBlockPos(), SoundEvents.ITEM_FRAME_REMOVE_ITEM, SoundSource.BLOCKS, 0.6F, 1.0F); setChanged(); diff --git a/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlock.java b/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlock.java index ec34b53..7ea4b27 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlock.java +++ b/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlock.java @@ -1,6 +1,5 @@ package io.ib67.sfcraft.module.game.crystal; -import com.mojang.serialization.MapCodec; import eu.pb4.polymer.core.api.block.PolymerBlock; import net.fabricmc.fabric.api.networking.v1.context.PacketContext; import net.minecraft.core.BlockPos; @@ -29,7 +28,6 @@ import java.util.function.BiFunction; public class GravityCrystalBlock extends BaseEntityBlock implements PolymerBlock { public static final IntegerProperty CHARGE = RespawnAnchorBlock.CHARGE; - public static final MapCodec CODEC = simpleCodec(GravityCrystalBlock::new); // GravityCrystalModule 注册方块实体类型后回填(方块与其方块实体类型互相引用,无法在构造器闭合) private BlockEntityType blockEntityType; @@ -46,11 +44,6 @@ public class GravityCrystalBlock extends BaseEntityBlock implements PolymerBlock this.blockEntityFactory = factory; } - @Override - protected MapCodec codec() { - return CODEC; - } - @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(CHARGE); diff --git a/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlockEntity.java b/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlockEntity.java index cc8b43d..5008f91 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlockEntity.java +++ b/src/main/java/io/ib67/sfcraft/module/game/crystal/GravityCrystalBlockEntity.java @@ -56,7 +56,7 @@ public class GravityCrystalBlockEntity extends BlockEntity { boosted = boosted.normalize().scale(maxSpeed); } entity.setDeltaMovement(boosted); - entity.hurtMarked = true; + entity.syncVelocity = true; } } diff --git a/src/main/java/io/ib67/sfcraft/module/game/mapart/MapArtModule.java b/src/main/java/io/ib67/sfcraft/module/game/mapart/MapArtModule.java index de624c2..4bd6117 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/mapart/MapArtModule.java +++ b/src/main/java/io/ib67/sfcraft/module/game/mapart/MapArtModule.java @@ -34,6 +34,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; +import net.minecraft.util.Prediction; import org.jspecify.annotations.Nullable; import javax.imageio.ImageIO; @@ -528,7 +529,7 @@ public class MapArtModule extends ServerModule { private static void give(ServerPlayer player, ItemStack stack) { if (!player.getInventory().add(stack)) { - player.drop(stack, false); + player.drop(stack, false, Prediction.SERVER_ONLY); } } diff --git a/src/main/java/io/ib67/sfcraft/module/game/portal/ElytraPortalModule.java b/src/main/java/io/ib67/sfcraft/module/game/portal/ElytraPortalModule.java index d9935b7..e824b9e 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/portal/ElytraPortalModule.java +++ b/src/main/java/io/ib67/sfcraft/module/game/portal/ElytraPortalModule.java @@ -109,7 +109,7 @@ public class ElytraPortalModule extends ServerModule { player.setDeltaMovement(recorded); // 玩家移动是客户端权威的,而客户端同样预测到了这次撞墙。不补一个速度包的话, // 服务端这边写回去的速度会立刻被客户端的位置汇报盖掉。 - player.hurtMarked = true; + player.syncVelocity = true; } public int getInstantTransitionTicks() { diff --git a/src/main/java/io/ib67/sfcraft/module/game/token/PearlTokenItem.java b/src/main/java/io/ib67/sfcraft/module/game/token/PearlTokenItem.java index 0391e99..80c1da9 100644 --- a/src/main/java/io/ib67/sfcraft/module/game/token/PearlTokenItem.java +++ b/src/main/java/io/ib67/sfcraft/module/game/token/PearlTokenItem.java @@ -22,6 +22,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.level.Level; +import net.minecraft.util.Prediction; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -93,7 +94,7 @@ public class PearlTokenItem extends Item implements PolymerItem { } else { stack.shrink(1); if (!player.getInventory().add(bound)) { - player.drop(bound, false); + player.drop(bound, false, Prediction.SERVER_ONLY); } } player.sendOverlayMessage(Component.translatable("message.sfcraft.token.bound")); diff --git a/src/main/java/io/ib67/sfcraft/module/room/CreativeRoomModule.java b/src/main/java/io/ib67/sfcraft/module/room/CreativeRoomModule.java index f08488a..de91580 100644 --- a/src/main/java/io/ib67/sfcraft/module/room/CreativeRoomModule.java +++ b/src/main/java/io/ib67/sfcraft/module/room/CreativeRoomModule.java @@ -211,7 +211,7 @@ public class CreativeRoomModule extends ServerModule { private int onQueryTime(CommandContext ctx) { var player = requirePlaygroundPlayer(ctx); if (player == null) return Command.SINGLE_SUCCESS; - long ticks = ctx.getSource().getServer().clockManager().getTotalTicks(playgroundClock(ctx.getSource())); + long ticks = ctx.getSource().getServer().clockManager().getInstance(playgroundClock(ctx.getSource())).totalTicks(); player.sendSystemMessage(Component.translatable("message.sfcraft.playground.time_query", wrapTime(ticks))); return Command.SINGLE_SUCCESS; }