本帖最后由 黎雨轩 于 2022-9-10 22:29 编辑 
这应该是一个关于Java的问题
是这样的,1.19.2之前的版本如果想要使TileEntity实现tick,只需要在你mod里TileEntity的子类覆写tick函数即可。
1.19.2实现方式变了,首先你绑定BlockEntity(TileEntity改成了BlockEntity)的方块得实现EntityBlock接口,覆写getTicker,其函数签名如下
复制代码返回的BlockEntityTicker是一个函数式接口:
复制代码
这是我覆写的getTicker:
复制代码返回的是我方块实体里面的一个静态方法
复制代码函数的第四个参数是BlockEntityMindOre  ,是BlockEntity的子类,满足泛型条件。
但是IDE里面会报错:Incompatible types: T is not convertible to BlockEntityMindOre
这应该是一个关于Java的问题
是这样的,1.19.2之前的版本如果想要使TileEntity实现tick,只需要在你mod里TileEntity的子类覆写tick函数即可。
1.19.2实现方式变了,首先你绑定BlockEntity(TileEntity改成了BlockEntity)的方块得实现EntityBlock接口,覆写getTicker,其函数签名如下
- @Nullable
 
-    default <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, BlockEntityType<T> pBlockEntityType) {
 
-       return null;
 
- }
- @FunctionalInterface
 
- public interface BlockEntityTicker<T extends BlockEntity> {
 
-    void tick(Level pLevel, BlockPos pPos, BlockState pState, T pBlockEntity);
 
- }
这是我覆写的getTicker:
- @Nullable
 
-     @Override
 
-     public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
 
-         return blockEntityType == BlockEntityTypesLibSC.BE_MINE_ORE.get() ? BlockEntityMindOre::tick : null;
 
- }
- public static void tick(Level level, BlockPos blockPos, BlockState blockState, BlockEntityMindOre blockEntity) {
 
-         if (level.isClientSide) {
 
-             if (blockEntity.heartBeatTimer == MAX_TIME) {
 
-                 int x = blockPos.getX();
 
-                 int y = blockPos.getY();
 
-                 int z = blockPos.getZ();
 
-                 double volumeModified;
 
-                 Player player = level.getNearestPlayer(x, y, z, MAX_DISTANCE, false);
 
-                 if (player != null) {
 
-                     volumeModified = 1 - Math.sqrt(player.distanceToSqr(x, y, z)) / MAX_DISTANCE;
 
-                     SaintChapter.LOGGER.info(String.format("Mind Ore Info:\ndistanceSqr: %f; distance: %f; volumeModifier: %f", player.distanceToSqr(x, y, z), Math.sqrt(player.distanceToSqr(x, y, z)),  volumeModified));
 
-                     level.playSound(player, blockPos, SoundsLibSC.HEART_BEAT.get(), SoundSource.BLOCKS, (float) (3 + 7 * volumeModified), 1f);
 
-                 }
 
-                 blockEntity.heartBeatTimer = 0;
 
-             }
 
-             blockEntity.heartBeatTimer++;
 
-         }
 
- }
但是IDE里面会报错:Incompatible types: T is not convertible to BlockEntityMindOre
非常Ok 但是我也不知道
看 Ticker 的定义:
复制代码
再看该方法的返回值泛型:
复制代码
此时返回值期望的是 BlockEntityTicker<T extends BlockEntity>,但你返回的是 BlockEntityTicker<BlockEntityMindOre>,T 的范围比 BlockEntityMindOre 大,需要强制转型,所以会提示你 Incompatible types: T is not convertible to BlockEntityMindOre。
解决办法:把 tick 的最后一个参数的类型变成 BlockEntity,然后在方法内强转成 BlockEntityMindOre。
或者你可以尝试让 getTicker 的返回值类型变为 BlockEntityTicker<BlockEntityMindOre>。
- @FunctionalInterface
 
- public interface BlockEntityTicker<T extends BlockEntity> {
 
-    void tick(Level pLevel, BlockPos pPos, BlockState pState, T pBlockEntity);
 
- }
再看该方法的返回值泛型:
- <T extends BlockEntity> BlockEntityTicker<T>
此时返回值期望的是 BlockEntityTicker<T extends BlockEntity>,但你返回的是 BlockEntityTicker<BlockEntityMindOre>,T 的范围比 BlockEntityMindOre 大,需要强制转型,所以会提示你 Incompatible types: T is not convertible to BlockEntityMindOre。
解决办法:把 tick 的最后一个参数的类型变成 BlockEntity,然后在方法内强转成 BlockEntityMindOre。
或者你可以尝试让 getTicker 的返回值类型变为 BlockEntityTicker<BlockEntityMindOre>。
秦千久 发表于 2022-9-11 11:20
看 Ticker 的定义:
再看该方法的返回值泛型:
感谢大佬耐心指导。
我实现的getTicker返回时已经判断了
- blockEntityType == BlockEntityTypesLibSC.BE_MINE_ORE.get()
这里的BlockEntityTypesLibSC.BE_MINE_ORE.get()是获取注册表注册的方块实体对象。
这就已经确定该函数式接口被调用时,传入的参数一定是BlockEntityType<BlockEntityMineOre>
本人java经验不足,以为编译器能够认识到这个已知条件。。
我发现原版提供了一个欺骗编译器的方法
- @Nullable
 
-     protected static <E extends BlockEntity, A extends BlockEntity> BlockEntityTicker<A> createTickerHelper(BlockEntityType<A> serverType, BlockEntityType<E> clientType, BlockEntityTicker<? super E> ticker) {
 
-         return clientType == serverType ? (BlockEntityTicker<A>)ticker : null;
 
- }
我觉得很有意思
黎雨轩 发表于 2022-9-11 12:05
感谢大佬耐心指导。
我实现的getTicker返回时已经判断了
也不算欺骗,这就是强制类型转换。
是这样的,1.19.2之前的版本如果想要使TileEntity实现tick,只需要在你mod里TileEntity的子类覆写tick函数即可。