[Legacy] GeckoLib Fabric

[Legacy] GeckoLib Fabric

3M Downloads

[1.18.2] Bug synchronized method with world (geckolib 3.0.57 latest 1.18.2 forge version)

ZUHOWKS opened this issue · 4 comments

commented

Hello,

I have a bug with my Blockling Entity Class. I check in my predicate() method if it's the night in the world to do a specific animation with a shouldSleep() method:

    // in BlocklingEntity class
    public boolean shouldSleep() {
        return !this.getCommandSenderWorld().isDay();
    }

This method return always false in my predicate() method even though it's the night.

    // in BlocklingEntity class
    public boolean shouldSleep() {
        return !this.getCommandSenderWorld().isDay();
    }

    private  <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) {

        if (event.isMoving() && this.shouldSleep()) {
            event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.blockling.walk2", ILoopType.EDefaultLoopTypes.LOOP));
        } else {
            event.getController().setAnimation(new AnimationBuilder()
                    .addAnimation("animation.blockling.idle3", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                    .addAnimation("animation.blockling.idle4", ILoopType.EDefaultLoopTypes.LOOP)
            );

        }

        return PlayState.CONTINUE;
    }

(So the animations in the else{...} are all time set)

My class is extends to Animal and implements IAnimatable, IAnimationTickable. I noticed that only the methods coming from the Entity super class like getOnPos() or interactAt() are synchronized and return the values ​​synchronized with the game (or the server but I don't know precisely):

     // in BlocklingEntity class
    private boolean shouldSleep = false; 
     
    @Override
    public @NotNull InteractionResult interactAt(@NotNull Player p_19980_, @NotNull Vec3 p_19981_, @NotNull InteractionHand hand) {
        if (hand == InteractionHand.MAIN_HAND) {
            this.shouldSleep= !this.shouldSleep; // Work !
        }

        return super.interactAt(p_19980_, p_19981_, hand);
    }
    
    private  <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) {

        if (event.isMoving() && this.shouldSleep) { // Work !
            event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.blockling.walk2", ILoopType.EDefaultLoopTypes.LOOP));
        } else {
            event.getController().setAnimation(new AnimationBuilder()
                    .addAnimation("animation.blockling.idle3", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                    .addAnimation("animation.blockling.idle4", ILoopType.EDefaultLoopTypes.LOOP)
            );

        }

        return PlayState.CONTINUE;
    }
    

I know your are not supporting this version but, consider this ticket to resolve the problem for all. Thank you !

commented

I set the night in the world. you can see in the console first the position and in next the value return by the method shouldSleep
image

The position value are updated. The value return by the method is always false
image

But in the baseTick method, the method return true:
image
image

I up some boolean but nothing work. How to fix it ?

commented

yes bro,today i meet the same problem ,so could you please tell me how do you work it out?

commented

Hello ! I come back to you with the repositery (if I'll find it). I believe I fixed it in the past.

commented

The predicate method is not synchronize with the server. Into predicate method, the entity data is not updated.

    private  <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) {

        if (event.isMoving() && !this.isRunning()) { // method able to get synched data
            event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.blockling.walk", ILoopType.EDefaultLoopTypes.LOOP));
        } else if (event.isMoving() && this.isRunning()) {
            if (!this.isRun()) {
                this.setIsRun(true);
            }
            event.getController().setAnimation(new AnimationBuilder()
                    //TODO: add start running animation
                    .addAnimation("animation.blockling.walk2", ILoopType.EDefaultLoopTypes.LOOP)
            );
        } else if (!event.isMoving()) { // method able to get synched data
            if (this.isHidden()) {
                if (!this.isSleeping()) {
                    if (this.isRun()) {
                        this.setIsRun(false);
                        event.getController().setAnimation(new AnimationBuilder()
                                //TODO: add stop running animation
                                .addAnimation("animation.blockling.idle3", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                                .addAnimation("animation.blockling.idle4", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                        );
                    } else {
                        event.getController().setAnimation(new AnimationBuilder()
                                .addAnimation("animation.blockling.idle3", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                                .addAnimation("animation.blockling.idle4", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                        );
                    }
                }


            } else if (this.isRun()) { // method able to get synched data
                this.setIsRun(false);
                event.getController().setAnimation(
                        new AnimationBuilder()
                                //TODO: add stop running animation
                                .addAnimation("animation.blockling.idle2", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                                .addAnimation("animation.blockling.idle", ILoopType.EDefaultLoopTypes.LOOP)
                );
            } else {
                if (this.isSleeping()) { // method able to get synched data
                    this.setSleeping(false);
                    event.getController().setAnimation(
                            new AnimationBuilder()
                                    //TODO: add stop sleeping animation
                                    .addAnimation("animation.blockling.idle2", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                                    .addAnimation("animation.blockling.idle", ILoopType.EDefaultLoopTypes.LOOP)
                    );
                } else {
                    event.getController().setAnimation(
                            new AnimationBuilder()
                                    .addAnimation("animation.blockling.idle2", ILoopType.EDefaultLoopTypes.PLAY_ONCE)
                                    .addAnimation("animation.blockling.idle", ILoopType.EDefaultLoopTypes.LOOP)
                    );
                }
            }
        }

        return PlayState.CONTINUE;
    }

In your entity class, thanks to the Entity class you can access to the attribute this.entityData correspond to the synched datas of your entity with the server. You can use this exemples to fix your problem:

    // define your custom data
    private static final EntityDataAccessor<Boolean> IS_SLEEPING = SynchedEntityData.defineId(BlocklingEntity.class, EntityDataSerializers.BOOLEAN);
   
   // to update your custom data
    public void setSleeping(boolean sleeping) {
        this.entityData.set(IS_SLEEPING, sleeping);
    }

   // to got it
    public boolean isSleeping() {
        return this.entityData.get(IS_SLEEPING);
    }
    ```